使用零依赖性基于种子和盐生成确定性 ECDSA/RSA 密钥

问题描述 投票:0回答:1

给定种子和盐,如何使用零依赖 JavaScript 和 SubtleCrypto 生成一组

确定性
ECDSA 密钥? (这是这个问题的延续。)

我的理解是有两种主要方法可以实现:

  1. 生成密钥材料,然后以某种方式将其导入为 ECDSA 密钥。
  2. 生成生成 ECDSA 密钥所需的
    x
    y
    (我不确定如何,因为
    generateKey
    仅接受命名曲线;也许通过 JWK?)

我希望解决方案尽可能依赖

SubtleCrypto
API,并使用尽可能少的自定义代码。

代码:

async function generateDeterministicECDSAKey(seed, salt) {
    // Step 1: Convert seed and salt to ArrayBuffers
    const enc = new TextEncoder();
    const seedBuffer = enc.encode(seed); // Seed as a buffer
    const saltBuffer = enc.encode(salt); // Salt as a buffer

    // Step 2: Derive key material using PBKDF2
    const baseKey = await crypto.subtle.importKey(
        'raw',
        seedBuffer,
        { name: 'PBKDF2' },
        false,
        ['deriveBits', 'deriveKey']
    );

    // Derive 256 bits (32 bytes) of key material for the private key
    const derivedBits = await crypto.subtle.deriveBits(
        {
            name: 'PBKDF2',
            salt: saltBuffer,  // Salt for PBKDF2
            iterations: 100000, // Use a secure iteration count
            hash: 'SHA-256'     // Hash function for PBKDF2
        },
        baseKey,
        256  // 256 bits for the derived key
    );

    // Step 3: Import derived key material as ECDSA private key
    // NOTE - that's where it fails due to a mismatch between the "raw" format
    // and  { name: 'ECDSA', namedCurve: 'P-256' } algo
    const privateKey = await crypto.subtle.importKey(
        'raw',
        derivedBits,  // Use derived bits as private key
        { name: 'ECDSA', namedCurve: 'P-256' },  // ECDSA using the P-256 curve
        true,  // Mark key as exportable
        ['sign']  // Key usage for signing
    );

    // Step 4: Export the private key in PKCS8 format (optional)
    const pkcs8Key = await crypto.subtle.exportKey('pkcs8', privateKey);
    
    // Step 5: Generate public key pair (optional)
    const publicKey = await crypto.subtle.exportKey('jwk', privateKey);

    return {
        privateKey: privateKey,
        pkcs8Key: pkcs8Key,
        publicKey: publicKey
    };
}

// Helper function to convert ArrayBuffer to base64 string (for display)
function arrayBufferToBase64(buffer) {
    const binary = String.fromCharCode.apply(null, new Uint8Array(buffer));
    return window.btoa(binary);
}

// Example usage
const seed = "your_deterministic_seed"; // Example seed
const salt = "your_salt_value";         // Example salt
await generateDeterministicECDSAKey(seed, salt).then(keys => {
    const privateKeyBase64 = arrayBufferToBase64(keys.pkcs8Key);
    console.log("Private Key (PKCS8 Base64):", privateKeyBase64);
    console.log("Public Key (JWK):", keys.publicKey);
});
javascript rsa digital-signature ecdsa subtlecrypto
1个回答
0
投票

此存储库是作为对涵盖 ECDSA 教育示例的问题的全面答案而创建的,无需任何外部模块即可在大多数现代浏览器上运行: https://github.com/RayRizzling/js-ecdsa

© www.soinside.com 2019 - 2024. All rights reserved.