【发布时间】:2022-07-16 04:11:31
【问题描述】:
我正在尝试使用我的身份证上的签名创建一个数字签名的 XML 文档。
我有两个部分的程序。第一个是从 ID 获取文件的证书和签名。 为此,我正在使用类似这样的 python PKCS11 库:
with open("input.xml", "rb") as f:
data = f.read()
lib = lib('path/to/pkcs11/lib.dylib')
token = lib.get_token('name of token')
with token.open(PIN) as session:
certificate = None
for obj in session.get_objects({Attribute.CLASS: ObjectClass.CERTIFICATE}):
certificate = obj
der_bytes = certificate[Attribute.VALUE]
with open('certificate.der', "wb") as f:
f.write(der_bytes)
# calculate SHA256 of data
digest = session.digest(data, mechanism=Mechanism.SHA256)
for obj in session.get_objects({Attribute.CLASS: ObjectClass.PRIVATE_KEY}):
private_key = obj
signature = private_key.sign(digest, mechanism=Mechanism.RSA_PKCS)
with open('signature', "wb") as f:
f.write(signature)
这会生成certificate.der 和signature 文件并且工作正常(至少我认为)
对于 XML 生成部分,我在 Java 中使用欧洲的 DSS 库,如下所示:
DSSDocument toSignDocument = new FileDocument("input.xml");
// Preparing parameters for the XAdES signature
XAdESSignatureParameters parameters = new XAdESSignatureParameters();
// We choose the level of the signature (-B, -T, -LT, -LTA).
parameters.setSignatureLevel(SignatureLevel.XAdES_BASELINE_B);
// We choose the type of the signature packaging (ENVELOPED, ENVELOPING, DETACHED).
parameters.setSignaturePackaging(SignaturePackaging.ENVELOPED);
// We set the digest algorithm to use with the signature algorithm. You must use the
// same parameter when you invoke the method sign on the token. The default value is SHA256 parameters.setDigestAlgorithm(DigestAlgorithm.SHA256);
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
InputStream in = new FileInputStream("certificate.der");
X509Certificate cert = (X509Certificate) certFactory.generateCertificate(in);
// We set the signing certificate
parameters.setSigningCertificate(new CertificateToken(cert));
// Create common certificate verifier
CommonCertificateVerifier commonCertificateVerifier = new CommonCertificateVerifier();
// Create XAdES service for signature
XAdESService service = new XAdESService(commonCertificateVerifier);
// Get the SignedInfo XML segment that need to be signed.
ToBeSigned dataToSign = service.getDataToSign(toSignDocument, parameters);
File file = new File("signature");
SignatureValue signatureValue = new SignatureValue(SignatureAlgorithm.RSA_SHA256, Files.readAllBytes(file.toPath()));
// We invoke the service to sign the document with the signature value obtained in
// the previous step.
DSSDocument signedDocument = service.signDocument(toSignDocument, parameters, signatureValue);
File signedFile = new File("output.xml");
signedFile.createNewFile();
signedDocument.writeTo(new FileOutputStream(signedFile, false));
这会创建 XAdES 文件,但是当我尝试验证签名(例如使用 this)时,它会说签名不完整。
我做错了什么?
【问题讨论】:
标签: digital-signature signature pkcs#11 xades