非对称签名验签
This commit is contained in:
parent
61f94f39cb
commit
81b0ea4c3b
@ -11,45 +11,49 @@ import com.sunyard.chsm.mapper.SpKeyRecordMapper;
|
|||||||
import com.sunyard.chsm.model.entity.AppCert;
|
import com.sunyard.chsm.model.entity.AppCert;
|
||||||
import com.sunyard.chsm.model.entity.KeyInfo;
|
import com.sunyard.chsm.model.entity.KeyInfo;
|
||||||
import com.sunyard.chsm.model.entity.KeyRecord;
|
import com.sunyard.chsm.model.entity.KeyRecord;
|
||||||
import com.sunyard.chsm.param.AsymDecryptReq;
|
import com.sunyard.chsm.param.*;
|
||||||
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.sdf.SdfApiService;
|
import com.sunyard.chsm.sdf.SdfApiService;
|
||||||
import com.sunyard.chsm.sdf.model.EccCipher;
|
import com.sunyard.chsm.sdf.model.EccCipher;
|
||||||
import com.sunyard.chsm.sdf.model.EccSignature;
|
import com.sunyard.chsm.sdf.model.EccSignature;
|
||||||
import com.sunyard.chsm.utils.CodecUtils;
|
import com.sunyard.chsm.utils.CodecUtils;
|
||||||
import com.sunyard.chsm.utils.gm.BCECUtils;
|
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 com.sunyard.chsm.utils.gm.cert.BCSM2CertUtils;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
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.X509CertificateHolder;
|
||||||
import org.bouncycastle.cert.jcajce.JcaCertStore;
|
import org.bouncycastle.cert.jcajce.JcaCertStore;
|
||||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
||||||
import org.bouncycastle.cms.CMSProcessableByteArray;
|
import org.bouncycastle.cms.*;
|
||||||
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.jcajce.JcaSignerInfoGeneratorBuilder;
|
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
|
||||||
import org.bouncycastle.cms.jcajce.JcaSignerInfoVerifierBuilder;
|
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.BCECPrivateKey;
|
||||||
|
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
|
import org.bouncycastle.operator.InputDecryptor;
|
||||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||||
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
|
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
|
||||||
import org.bouncycastle.util.Store;
|
import org.bouncycastle.util.Store;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.Assert;
|
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.security.cert.X509Certificate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -235,7 +239,7 @@ public class AsymKeyService {
|
|||||||
return resp;
|
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 {
|
try {
|
||||||
BCECPrivateKey privateKey = BCECUtils.createPrivateKey(pri);
|
BCECPrivateKey privateKey = BCECUtils.createPrivateKey(pri);
|
||||||
X509Certificate x509Cert = BCSM2CertUtils.getX509Cert(cert);
|
X509Certificate x509Cert = BCSM2CertUtils.getX509Cert(cert);
|
||||||
@ -290,6 +294,81 @@ public class AsymKeyService {
|
|||||||
return false;
|
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) {
|
private KeyInfo checkKey(Long keyId, KeyUsage usage) {
|
||||||
|
|
||||||
KeyInfo keyInfo = keyInfoMapper.selectById(keyId);
|
KeyInfo keyInfo = keyInfoMapper.selectById(keyId);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user