非对称签名验签

This commit is contained in:
liulu 2024-12-24 14:25:54 +08:00
parent 61f94f39cb
commit 81b0ea4c3b

View File

@ -11,45 +11,49 @@ import com.sunyard.chsm.mapper.SpKeyRecordMapper;
import com.sunyard.chsm.model.entity.AppCert;
import com.sunyard.chsm.model.entity.KeyInfo;
import com.sunyard.chsm.model.entity.KeyRecord;
import com.sunyard.chsm.param.AsymDecryptReq;
import com.sunyard.chsm.param.AsymDecryptResp;
import com.sunyard.chsm.param.AsymEncryptReq;
import com.sunyard.chsm.param.AsymEncryptResp;
import com.sunyard.chsm.param.AsymSignP7Req;
import com.sunyard.chsm.param.AsymSignP7Resp;
import com.sunyard.chsm.param.AsymSignRawReq;
import com.sunyard.chsm.param.AsymSignRawResp;
import com.sunyard.chsm.param.AsymVerifyP7Req;
import com.sunyard.chsm.param.AsymVerifyRawReq;
import com.sunyard.chsm.param.VerifyResp;
import com.sunyard.chsm.param.*;
import com.sunyard.chsm.sdf.SdfApiService;
import com.sunyard.chsm.sdf.model.EccCipher;
import com.sunyard.chsm.sdf.model.EccSignature;
import com.sunyard.chsm.utils.CodecUtils;
import com.sunyard.chsm.utils.gm.BCECUtils;
import com.sunyard.chsm.utils.gm.BCSM2Utils;
import com.sunyard.chsm.utils.gm.BCSM4Utils;
import com.sunyard.chsm.utils.gm.cert.BCSM2CertUtils;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.cms.*;
import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.SignerInfoGenerator;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.cms.*;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.cms.jcajce.JcaSignerInfoVerifierBuilder;
import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.jcajce.io.CipherInputStream;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.InputDecryptor;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.Store;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.InputStream;
import java.security.Key;
import java.security.cert.X509Certificate;
import java.time.LocalDateTime;
import java.util.Collection;
@ -235,7 +239,7 @@ public class AsymKeyService {
return resp;
}
private static byte[] p7Sign(byte[] pri, String cert, byte[] plainData, boolean encapsulate) {
private byte[] p7Sign(byte[] pri, String cert, byte[] plainData, boolean encapsulate) {
try {
BCECPrivateKey privateKey = BCECUtils.createPrivateKey(pri);
X509Certificate x509Cert = BCSM2CertUtils.getX509Cert(cert);
@ -290,6 +294,81 @@ public class AsymKeyService {
return false;
}
@SneakyThrows
private byte[] makeEnvelopeData(byte[] srcMsg, byte[] certData) {
X509Certificate cert = BCSM2CertUtils.getX509Certificate(certData);
AlgorithmIdentifier symAlg = new AlgorithmIdentifier(GMObjectIdentifiers.sm_scheme.branch("104")); // sm4
AlgorithmIdentifier asymAlg = new AlgorithmIdentifier(GMObjectIdentifiers.sm2encrypt, DERNull.INSTANCE);
byte[] symKey = sdfApiService.generateRandom(16);
BCECPublicKey publicKey = (BCECPublicKey) cert.getPublicKey();
byte[] encryptKey = BCSM2Utils.encrypt(publicKey, symKey);
X500Name x500Name = X500Name.getInstance(cert.getIssuerX500Principal().getEncoded());
KeyTransRecipientInfo keyTransRecipientInfo = new KeyTransRecipientInfo(
new RecipientIdentifier(new IssuerAndSerialNumber(x500Name, cert.getSerialNumber())),
asymAlg,
new DEROctetString(encryptKey)
);
byte[] encContent = BCSM4Utils.encrypt_ECB_Padding(symKey, srcMsg);
RecipientInfo recipientInfo = new RecipientInfo(keyTransRecipientInfo);
EncryptedContentInfo encContentInfo = new EncryptedContentInfo(
new ASN1ObjectIdentifier("1.2.156.10197.6.1.4.2.1"),
symAlg,
new DEROctetString(encContent)
);
EnvelopedData envelopedData = new EnvelopedData(null,
new DERSet(recipientInfo),
encContentInfo,
(org.bouncycastle.asn1.ASN1Set) null);
ContentInfo contentInfo = new ContentInfo(new ASN1ObjectIdentifier("1.2.156.10197.6.1.4.2.3"), envelopedData);
return contentInfo.getEncoded("DER");
}
@SneakyThrows
private byte[] decryptEnvelopeData(byte[] envelopeData, byte[] priKeyD) {
ECPrivateKeyParameters priKeyParameters = BCECUtils.createECPrivateKeyParameters(priKeyD);
final BCECPrivateKey priKey = new BCECPrivateKey("EC", priKeyParameters, BouncyCastleProvider.CONFIGURATION);
// 解密数字信封
CMSEnvelopedData ed = new CMSEnvelopedData(envelopeData);
RecipientInformationStore recipientInfos = ed.getRecipientInfos();
Collection<RecipientInformation> recipients = recipientInfos.getRecipients();
RecipientInformation next = recipients.iterator().next();
return next.getContent(new JceKeyTransEnvelopedRecipient(priKey) {
@Override
@SneakyThrows
public RecipientOperator getRecipientOperator(AlgorithmIdentifier keyEncAlg,
AlgorithmIdentifier contentEncryptionAlgorithm,
byte[] encryptedContentKey) {
String keyEncId = keyEncAlg.getAlgorithm().getId();
if (Objects.equals(GMObjectIdentifiers.sm2encrypt.getId(), keyEncId)) {
byte[] keyBytes = BCSM2Utils.decrypt(priKeyParameters, encryptedContentKey);
Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS7Padding", BouncyCastleProvider.PROVIDER_NAME);
Key sm4Key = new SecretKeySpec(keyBytes, "SM4");
cipher.init(Cipher.DECRYPT_MODE, sm4Key);
return new RecipientOperator(new InputDecryptor() {
@Override
public AlgorithmIdentifier getAlgorithmIdentifier() {
return contentEncryptionAlgorithm;
}
@Override
public InputStream getInputStream(InputStream dataIn) {
return new CipherInputStream(dataIn, cipher);
}
});
}
return super.getRecipientOperator(keyEncAlg, contentEncryptionAlgorithm, encryptedContentKey);
}
}.setProvider(BouncyCastleProvider.PROVIDER_NAME));
}
private KeyInfo checkKey(Long keyId, KeyUsage usage) {
KeyInfo keyInfo = keyInfoMapper.selectById(keyId);