我试图以CreateSignature为例作为起点,并对其进行更改以使其与基于外部网络的HSM系统一起使用。
生成的PDF文档始终抱怨“文档已被更改”。我缺乏关于应该使用什么签名的见识。
以下是我的CreateSignatureBase.java中sign()的实现:
@Override
public byte[] sign(InputStream content) throws IOException {
// cannot be done private (interface)
try {
// Certificate chain is acquired at initialization
List<Certificate> certList = new ArrayList<>();
certList.addAll(Arrays.asList(certificateChain));
Store<?> certs = new JcaCertStore(certList);
org.bouncycastle.asn1.x509.Certificate cert = org.bouncycastle.asn1.x509.Certificate.getInstance(certificateChain[0].getEncoded());
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
//HSMSigner is the class that interacts with the network HSM to get the signature.
HSMSigner signer = new HSMSigner();
byte[] input = IOUtil.toByteArray(content);
//SignedHash is a base64-encoded PKCS1 block. see HSMSigner.getSignature() below
final String signedHash = signer.getSignature(input);
ContentSigner sha1Signer = new ContentSigner() {
@Override
public byte[] getSignature() {
return Base64.getDecoder().decode(signedHash);
}
@Override
public OutputStream getOutputStream() {
return new ByteArrayOutputStream();
}
@Override
public AlgorithmIdentifier getAlgorithmIdentifier() {
return new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WITHRSAENCRYPTION");
}
};
gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build()).build(sha1Signer, new X509CertificateHolder(cert)));
gen.addCertificates(certs);
CMSProcessableInputStream msg = new CMSProcessableInputStream(content);
CMSSignedData cmsSignedData = gen.generate(msg, true);
byte[] result = cmsSignedData.getEncoded();
return result;
} catch (GeneralSecurityException | CMSException | OperatorCreationException e) {
throw new IOException(e);
}
}
以下是HSMSigner()。getSignature()
的实现public String getSignature(byte [] bytes) {
String host = "hsmvip.corp.com";
int port = 9000;
SignClient signClient;
try {
//initialize the sign client
signClient = ///..;
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(bytes);
byte[] outputDigest = messageDigest.digest();
// signature returned by the sign method is a base64-encoded PKCS1 block.
String signature = signClient.sign(Base16.encodeAsString(outputDigest));
signClient.close();
return signature;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
任何帮助我弄清楚自己在做错什么的人,都表示赞赏。
可以在https://file.io/2tVvYO上找到签名pdf的副本
谢谢!
答案 0 :(得分:1)
感谢您的详细答复,我能够按如下所示更新CreateSignatureBase.sign()方法以获得所需的结果
CreateSignautreBase.java:sign()
listViewUsers.Items.Clear();
dsUsers = aUser.GetUserNamesList(int.Parse(clientId));
int rowsCount = dsUsers.Tables["UserNames"].Rows.Count;
for (int i = 0; i < rowsCount; i++)
{
dRow = dsUsers.Tables["UserNames"].Rows[i];
lvi = new ListViewItem("item" + i, i);
lvi.SubItems.Add(dRow["User_ID"].ToString().Trim());
lvi.SubItems.Add(dRow["User Name"].ToString().Trim());
listViewUsers.Items.Add(lvi);
}
HSMSigner.getSignature()保持不变。