在国内做金融行业,难免会有被强制使用国密算法的情况,而且一般还会指定必须使用硬件加密机之类的设备,所以我也稍微的研究了一下国密算法,使用软算法签名并封装PKCS7
格式(文档中的一个交互)。
以下是基于Bouncy Castle
的示例,密钥对的生成可以参考Bouncy Castle
中test
包下SM2
相关代码
public static String sign() throws Exception {
//加载公钥
byte[] plainText = "hello, world".getBytes();
FileInputStream input = new FileInputStream("F:\\certificate\\public.cer");
CertificateFactory certificateFactory = new CertificateFactory();
X509Certificate certificate = (X509Certificate)certificateFactory.engineGenerateCertificate(input);
input.close();
//加载私钥,private为换成实际的私钥
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec("private".getBytes());
//SM2算法实际上为ECC算法,并指定了一些参数值,所以这里的参数是EC
KeyFactory factory = KeyFactory.getInstance("EC", "BC");
PrivateKey privateKey = factory.generatePrivate(spec);
//以下为签名并封装成PKCS7格式
byte[] signedMessage;
List<X509Certificate> certList = new ArrayList<>();
CMSTypedData cmsData= new CMSProcessableByteArray(plainText);
certList.add(certificate);
JcaCertStore certs = new JcaCertStore(certList);
CMSSignedDataGenerator cmsGenerator = new CMSSignedDataGenerator();
ContentSigner contentSigner = new JcaContentSignerBuilder("SM3withSM2").build(privateKey);
cmsGenerator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(
new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
.build(contentSigner, certificate));
cmsGenerator.addCertificates(certs);
CMSSignedData cms = cmsGenerator.generate(cmsData, true);
signedMessage = cms.getEncoded();
return Base64.getEncoder().encodeToString(signedMessage);
}
评论
发表评论