使用AWS KMS签名PDF遇异常及签名有效性问题求助
问题1:Broken Pipe异常的排查与修复
出现Broken pipe错误,大概率是请求参数不完整或客户端配置问题,按以下步骤排查修复:
- 必须指定签名算法:AWS KMS的
Sign接口要求显式指定签名算法,你的代码只传了KeyId和Message,缺少SigningAlgorithm参数。RSA_2048密钥支持多种签名算法(如SHA256、SHA512),KMS无法自动推断,修改代码如下:SignRequest signRequest = new SignRequest() .withKeyId(keyId) .withMessage(ByteBuffer.wrap(pdfBytes)) .withSigningAlgorithm(SigningAlgorithmSpec.RSASSA_PKCS1_V1_5_SHA_256); // 根据需求选择对应算法 - 调整客户端超时配置:如果PDF文件过大,默认超时时间可能导致连接断开,给KMS客户端添加超时设置:
ClientConfiguration clientConfig = new ClientConfiguration(); clientConfig.setConnectionTimeout(5000); // 5秒连接超时 clientConfig.setSocketTimeout(30000); // 30秒读写超时 AWSKMS kmsClient = AWSKMSClientBuilder.standard() .withCredentials(credentialsProvider) .withRegion(Config.region) .withClientConfiguration(clientConfig) .build(); - 验证密钥与凭证有效性:确认
MY-KEY-ID是正确的密钥ARN、别名或ID;检查IAM用户的accesskey/secretkey是否正确,权限策略是否生效(可通过AWS CLI执行kms sign命令验证权限)。
问题2:让Adobe Reader认可PDF签名(消除“签名有效性未知”)
你当前直接签名整个PDF字节流的方式不符合PDF签名规范,Adobe要求签名遵循PKCS#7/CMS标准,且需包含可验证的证书链,具体步骤如下:
核心流程
- 获取KMS密钥的证书链:调用KMS的
GetPublicKey接口获取密钥对应的公钥证书(AWS托管密钥自带证书链,自定义密钥需确保已上传对应证书):GetPublicKeyRequest getPubKeyReq = new GetPublicKeyRequest().withKeyId(keyId); GetPublicKeyResult getPubKeyRes = kmsClient.getPublicKey(getPubKeyReq); // 解析证书为X509Certificate对象 CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(getPubKeyRes.getPublicKey().array())); - 用PDF库创建签名占位符并计算待签哈希:推荐使用iText 7处理PDF签名,先在PDF中预留签名位置,计算排除签名值后的文档哈希(而非整个PDF):
PdfReader reader = new PdfReader(new ByteArrayInputStream(pdf.toByteArray())); ByteArrayOutputStream baos = new ByteArrayOutputStream(); PdfSigner signer = new PdfSigner(reader, baos, new StampingProperties()); // 设置签名显示属性 PdfSignatureAppearance appearance = signer.getSignatureAppearance(); appearance.setReason("Document signed via AWS KMS"); appearance.setLocation("AWS"); // 对接KMS签名逻辑,指定哈希算法(需与KMS签名算法匹配) ExternalDigest digest = new BouncyCastleDigest(); ExternalSignature signature = new AwsKmsSignature(kmsClient, keyId, SigningAlgorithmSpec.RSASSA_PKCS1_V1_5_SHA_256); signer.signDetached(digest, signature, new Certificate[]{cert}, null, null, null, 0, PdfSigner.CryptoStandard.CMS); - 自定义KMS签名实现:实现iText的
ExternalSignature接口,仅对文档哈希进行签名:public class AwsKmsSignature implements ExternalSignature { private final AWSKMS kmsClient; private final String keyId; private final SigningAlgorithmSpec algorithm; public AwsKmsSignature(AWSKMS kmsClient, String keyId, SigningAlgorithmSpec algorithm) { this.kmsClient = kmsClient; this.keyId = keyId; this.algorithm = algorithm; } @Override public String getEncryptionAlgorithm() { return "RSA"; // 匹配你的密钥类型 } @Override public String getHashAlgorithm() { return algorithm.name().split("_SHA_")[1]; // 提取哈希算法,如SHA256 } @Override public byte[] sign(byte[] message) throws GeneralSecurityException { try { SignRequest request = new SignRequest() .withKeyId(keyId) .withMessage(ByteBuffer.wrap(message)) .withSigningAlgorithm(algorithm); SignResult result = kmsClient.sign(request); return result.getSignature().array(); } catch (SdkException e) { throw new GeneralSecurityException(e); } } } - 确保证书信任链有效:Adobe会验证签名证书的信任链,若为AWS托管证书,需确认AWS根CA在Adobe信任列表中;若为自定义证书,需将根CA导入Adobe信任存储(路径:编辑>首选项>签名>身份与信任证书)。
内容的提问来源于stack exchange,提问作者reshef_
相关产品推荐
相关产品推荐

