如何将Java PKCS7数据签名代码转换为Node.js?求BouncyCastle替代方案
Convert Java BouncyCastle PKCS7 Signature to Node.js
Got it, let's break down how to replicate your Java PKCS7 signing logic in Node.js. Your original code uses BouncyCastle to generate a SHA1withRSA CMS (PKCS7) signature from a JKS keystore, then outputs the Base64-encoded result. Here's a complete implementation with explanations:
Step 1: Install Dependencies
We'll use two libraries to match the Java functionality:
jks-js: To read the JKS keystore (Node.js doesn't natively support JKS)node-forge: To handle PKCS7/CMS signing (our equivalent to BouncyCastle for Node.js)
Install them via npm:
npm install jks-js node-forge
Step 2: Node.js Implementation
This code mirrors every key step from your Java code:
const jks = require('jks-js'); const forge = require('node-forge'); /** * Generates a PKCS7 (CMS) signature matching the Java BouncyCastle implementation * @param {string} content - The string content to sign * @param {string} jksPath - Path to your JKS keystore file * @param {string} keystorePassword - Password for the JKS keystore * @param {string} keyPassword - Password for the private key (often same as keystore password) * @returns {string} Base64-encoded PKCS7 signature */ function getSignature(content, jksPath, keystorePassword, keyPassword) { // 1. Load JKS keystore (matches Java's KeyStore.getInstance("jks")) const keystore = jks.load(jksPath, keystorePassword); // 2. Find the first key entry in the keystore (matches Java's alias enumeration logic) const keyAlias = Object.keys(keystore.keyEntries)[0]; if (!keyAlias) { throw new Error("No key entries found in JKS keystore"); } const keyEntry = keystore.keyEntries[keyAlias]; // 3. Convert JKS private key to forge-compatible format const privateKeyDer = forge.util.createBuffer(keyEntry.privateKey); const privateKey = forge.pki.privateKeyFromAsn1(forge.asn1.fromDer(privateKeyDer)); // 4. Convert certificate chain to forge-compatible certificates const certs = []; keyEntry.certificateChain.forEach(certDer => { const certBuffer = forge.util.createBuffer(certDer); const cert = forge.pki.certificateFromAsn1(forge.asn1.fromDer(certBuffer)); certs.push(cert); }); // 5. Create PKCS7 signed data (matches Java's CMSSignedDataGenerator) const p7 = forge.pkcs7.createSignedData(); p7.content = forge.util.createBuffer(content, 'utf8'); // 6. Add signer with SHA1-RSA algorithm (matches Java's SHA1withRSA) p7.addSigner({ key: privateKey, certificate: certs[0], digestAlgorithm: forge.pki.oids.sha1, authenticatedAttributes: [ { type: forge.pki.oids.contentType, value: forge.pki.oids.data }, { type: forge.pki.oids.messageDigest }, { type: forge.pki.oids.signingTime, value: new Date() } ] }); // 7. Add the full certificate chain to the signature (matches addCertificatesAndCRLs) p7.addCertificates(certs); // 8. Generate detached signature (matches Java's generate(..., true)) p7.sign({detached: true}); // 9. Encode the signature to DER, then Base64 (matches Java's getEncoded() + Base64.encode) const derBytes = forge.asn1.toDer(p7.toAsn1()).getBytes(); return forge.util.encode64(derBytes); } // Example usage (matches Java's main method) try { const content = process.argv[2]; const signature = getSignature( content, './keystore.jks', 'password', 'password' ); console.log(signature); } catch (err) { console.error("Signing failed:", err.message); }
Key Notes Matching Your Java Code
- JKS Handling: Uses
jks-jsto load and parse the JKS keystore, just like Java'sKeyStoreclass - Signature Algorithm: Explicitly uses SHA1 with RSA, matching your
SHA1withRSAandDIGEST_SHA1settings - Detached Signature: The
detached: trueoption matches the secondtrueparameter in Java'sgenerator.generate(..., true) - Certificate Chain: Includes the full certificate chain in the PKCS7 signature, just like
addCertificatesAndCRLs - Base64 Output: Encodes the final DER signature to Base64, identical to Java's
Base64.encode(signedData)
Important Considerations
- SHA1 Security: SHA1 is cryptographically weak. If the third-party API supports it, consider upgrading to SHA256withRSA (you'd just change
digestAlgorithmtoforge.pki.oids.sha256and update the Java code's algorithm if needed) - Keystore Passwords: Ensure the
keyPasswordmatches the password for the private key in your JKS (often the same as the keystore password, as in your Java code) - Error Handling: Added basic error handling; you can extend this to match your application's needs
内容的提问来源于stack exchange,提问作者ddd
相关产品推荐
相关产品推荐

