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

如何在TypeScript中复刻C#的ECDH密钥对生成及共享密钥计算代码?

TypeScript复刻C# ECDH密钥对生成与共享密钥计算功能问题

原C#代码功能

这段C#代码用于基于ECDH协议生成密钥对并计算共享密钥:输入64字节的productKey,输出32字节的共享密钥,同时返回本地生成的64字节公钥。

public static byte[] CreateECDHAddHockKey(byte[] productKey, ref byte[] publicKey) {
    //productKey is byte[64]
    //BCRYPT_ECDH_PUBLIC_P256_MAGIC = 0x314B4345,
    //var keyType = new byte[] { 0x45, 0x43, 0x53, 0x31 };
    //var keyLength = new byte[] { 0x20, 0x00, 0x00, 0x00 };
    byte[] PublicP256Header = new byte[] { 0x45, 0x43, 0x4B, 0x31, 0x20, 0x00, 0x00, 0x00 }; //8 bytes
    byte[] completeKey = new byte[productKey.Length + PublicP256Header.Length]; //8+64 = 72 bytes
    Array.Copy(PublicP256Header, completeKey, PublicP256Header.Length);
    Array.Copy(productKey, 0, completeKey, PublicP256Header.Length, productKey.Length);
    CngKey key = CngKey.Import(completeKey, CngKeyBlobFormat.EccPublicBlob);
    ECDiffieHellmanCng MyKey = new ECDiffieHellmanCng(256);
    MyKey.HashAlgorithm = CngAlgorithm.Sha256;
    MyKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
    var sharedSecret = MyKey.DeriveKeyMaterial(key); //32 bytes
    publicKey = MyKey.Key.Export(CngKeyBlobFormat.EccPublicBlob).Skip(8).ToArray(); //64 bytes
    return sharedSecret;
}

当前问题

尝试用TypeScript的crypto模块复刻上述功能时,遇到格式错误和输出长度不符的问题,当前写出的代码如下:

import crypto, { KeyObject } from 'crypto';
function generateKeyPairSync(data: Uint8Array): {
  publicKey: KeyObject;
  sharedSecret: KeyObject;
} {
  //generate key pair using ecc public blob
  const keyPair = crypto.generateKeyPairSync('ed25519', {
    publicKeyEncoding: {
      type: 'spki',
      format: 'der',
      data,
    },
  });

  return {
    publicKey: keyPair.publicKey,
    sharedSecret: keyPair.privateKey,
  };
}

正确实现方案

要复刻C#代码功能,需注意核心细节:C#使用P-256曲线(而非TS代码中的Ed25519签名曲线)、处理C#专属的EccPublicBlob格式转换、用SHA256作为密钥派生哈希算法。以下是符合要求的TypeScript实现:

import crypto from 'crypto';

function createECDHAdHocKey(productKey: Uint8Array): { sharedSecret: Buffer; publicKey: Buffer } {
    // 1. 构造C#格式的EccPublicBlob(头部+productKey)
    const publicP256Header = Buffer.from([0x45, 0x43, 0x4B, 0x31, 0x20, 0x00, 0x00, 0x00]);
    const completeKey = Buffer.concat([publicP256Header, productKey]);

    // 2. 解析EccPublicBlob为Node.js支持的SPKI格式公钥
    const rawPublicKey = completeKey.subarray(8);
    const x = rawPublicKey.subarray(0, 32);
    const y = rawPublicKey.subarray(32, 64);
    const spkiDer = createP256SPKI(x, y);

    // 3. 生成本地P-256曲线ECDH密钥对
    const ecdh = crypto.createECDH('prime256v1'); // prime256v1对应P-256曲线
    const localPublicKeyBuffer = ecdh.generateKeys();

    // 4. 计算共享密钥并通过SHA256哈希(匹配C#的密钥派生规则)
    const sharedSecretRaw = ecdh.computeSecret(spkiDer);
    const sharedSecret = crypto.createHash('sha256').update(sharedSecretRaw).digest();

    // 5. 提取本地公钥的原始x+y字节(对应C#跳过头部后的输出)
    const localRawPublicKey = extractRawP256PublicKey(localPublicKeyBuffer);

    return {
        sharedSecret,
        publicKey: localRawPublicKey
    };
}

// 辅助函数:从x、y构造P-256曲线的SPKI格式DER公钥
function createP256SPKI(x: Buffer, y: Buffer): Buffer {
    // P-256曲线的OID标识
    const oid = Buffer.from([0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07]);
    // 未压缩公钥结构:0x04标识 + x + y
    const publicKeyData = Buffer.concat([Buffer.from([0x04]), x, y]);
    // 组装ASN.1 DER格式的SPKI公钥
    return Buffer.concat([
        Buffer.from([0x30, 0x59]),
        Buffer.from([0x30, 0x13]),
        oid,
        Buffer.from([0x05, 0x00]),
        Buffer.from([0x03, 0x42, 0x00]),
        publicKeyData
    ]);
}

// 辅助函数:从Node.js生成的公钥中提取原始x+y字节(64字节)
function extractRawP256PublicKey(publicKeyBuffer: Buffer): Buffer {
    // 跳过SPKI格式的ASN.1头部,提取x+y部分并去掉0x04标识位
    return publicKeyBuffer.subarray(26, 26 + 65).subarray(1);
}

核心匹配点

  • 曲线统一:使用prime256v1对应C#的P-256
  • 格式兼容:手动实现EccPublicBlob与SPKI格式的转换
  • 密钥派生:共享密钥生成后用SHA256哈希,与C#代码逻辑完全一致
  • 输出对齐:本地公钥输出64字节的x+y原始数据,匹配C#跳过头部后的结果

内容的提问来源于stack exchange,提问作者omer5611

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 16:45:16