目前,我有一个类,我可以正确地生成一个cms签名本地(访问私钥)。我需要调整它,使签名操作在一个异步响应请求的外部服务器上完成(我只能访问公共证书),因此我想找到一种方法获取必须签名的摘要,将其发送到服务器并退出。
当收到响应时,我将构建cms容器并插入它。
我知道我可以创建一个contentsigner,它不签署数据,而是返回签署的数据。但是我怎样才能得到真正需要签名的摘要呢?
我有一个执行签名的类
public class MyContentSigner implements ContentSigner {
private final Signature sign;
private final ByteArrayOutputStream byteArrayOutputStream;
private final AlgorithmIdentifier sha256withRSA;
public MyContentSigner(PrivateKey privateKey, AlgorithmIdentifier sha256withRSA) throws NoSuchAlgorithmException, InvalidKeyException {
this.sha256withRSA = sha256withRSA;
sign = Signature.getInstance("SHA256withRSA", new BouncyCastleProvider());
sign.initSign(privateKey);
byteArrayOutputStream = new ByteArrayOutputStream();
}
@Override
public AlgorithmIdentifier getAlgorithmIdentifier() {
return sha256withRSA;
}
@Override
public OutputStream getOutputStream() {
return byteArrayOutputStream;
}
@Override
public byte[] getSignature() {
try {
byte[] input = byteArrayOutputStream.toByteArray();
this.sign.update(input);
byteArrayOutputStream.reset();
return this.sign.sign();
} catch (SignatureException e) {
e.printStackTrace();
}
return null;
}
}
然后这个类创建cms容器并将前一个类设置为contentsigner。
public class SignServiceWithMyContentSigner {
private final PrivateKey privateKey;
private final X509Certificate certificate;
public static final String SIGNATURE_ALGORITHM = "SHA256withRSA";
private final Certificate[] chain;
public SignServiceWithMyContentSigner(KeyStore ks) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException {
privateKey = (PrivateKey) ks.getKey("....", "".toCharArray());
certificate = (X509Certificate) ks.getCertificate("....");
chain = ks.getCertificateChain(".....");
}
public byte[] signDocument(byte[] digestInfo) {
try {
List<Certificate> certificateList = Arrays.asList(chain);
JcaCertStore jcaCertStore = new JcaCertStore(certificateList);
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
Attribute attribute = new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(digestInfo)));
ASN1EncodableVector asn1EncodableVector = new ASN1EncodableVector();
asn1EncodableVector.add(attribute);
SignerInfoGeneratorBuilder builder =
new SignerInfoGeneratorBuilder(
new BcDigestCalculatorProvider()
).setSignedAttributeGenerator(
new DefaultSignedAttributeTableGenerator(
new AttributeTable(asn1EncodableVector)
)
);
AlgorithmIdentifier sha256withRSA = new DefaultSignatureAlgorithmIdentifierFinder().find(SIGNATURE_ALGORITHM);
generator.addSignerInfoGenerator(
builder.build(
// Here is the my previous class
new MyContentSigner(privateKey, sha256withRSA),
new JcaX509CertificateHolder(certificate)
)
);
generator.addCertificates(jcaCertStore);
CMSSignedData generate = generator.generate(new CMSAbsentContent(), false);
return generate.getEncoded();
} catch (IOException | CertificateEncodingException | OperatorCreationException | CMSException | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
}
return new byte[0];
}
}
暂无答案!
目前还没有任何答案,快来回答吧!