You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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-js to load and parse the JKS keystore, just like Java's KeyStore class
  • Signature Algorithm: Explicitly uses SHA1 with RSA, matching your SHA1withRSA and DIGEST_SHA1 settings
  • Detached Signature: The detached: true option matches the second true parameter in Java's generator.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 digestAlgorithm to forge.pki.oids.sha256 and update the Java code's algorithm if needed)
  • Keystore Passwords: Ensure the keyPassword matches 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:49:18