Python和Node之间的Diffie-Hellman密钥交换失败,并显示错误所提供的密钥太大

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

[我正在尝试在具有最新节点映像(节点版本:v13.10.1)的Docker容器中运行的Python 3.6客户端与节点服务器之间进行DH密钥交换。

我正在python客户端使用cryptography.io(2.9.2)库。客户端生成DH密钥,并将十六进制编码的公共密钥发送到服务器。这是代码段:

MODP15_HEX_PRIME = "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff"

...

def generate_DH_key():
    # MODP 15 -> generator=2, key_size=3072 https://www.rfc-editor.org/rfc/rfc3526.txt

    dh_parameters = dh.DHParameterNumbers(p=int(MODP15_HEX_PRIME, 16), g=2).parameters(backend=default_backend())

    client_private_dh_key = dh_parameters.generate_private_key()

    return client_private_dh_key

def send_signed_dh_key(client_public_dh_key):
    dh_key_bytes = client_public_dh_key.public_bytes(encoding=serialization.Encoding.DER,                                                     format=serialization.PublicFormat.SubjectPublicKeyInfo)

    response = requests.post(CRYPTO_ORACLE_URL, headers=CRYPTO_ORACLE_HEADERS,
                             data=json.dumps({'key': dh_key_bytes.hex()))

    if response.status_code != 200:
        print('Something went wrong sending client signed DH: ' + response.reason)
        exit(-1)

服务器使用加密库根据收到的DH密钥计算机密。这是代码段:

const generateSecret=(clientDHPublic)=>{
    ...
    serverDH = crypto.getDiffieHellman("modp15");
    serverDH.generateKeys();

    console.log("server DH public:")
    console.log(serverDH.getPublicKey("hex"));
    console.log("client DH public:");
    console.log(clientDHPublic.toString("hex"));

    const dhSharedKey = serverDH.computeSecret(clientDHPublic);
    ...
}

我记录了两个公共密钥只是为了比较结构,我不希望它们明显相同。输出类似于:

server DH public:

8d367904f51854c3625ac85aec99f21b55963a583746302261f2299b9423f77a335607b2826d3d57695c16eb0b798720aed11d7d13704bcf1d68f05df9d29a00f374cc9b60095fb942be495a0f8a116d1e41761da7c1c403e174ea5715a5e1ff34cc9b409787fe48678141a095c26694c85ca52939b0c1b888f0a630ed8e1d8511cae7cf6ed6c3032cd32ab42743c6c635b984f5527058c159a38eaa2f23ba6b40cee58321349ca8ff4602273cbccb6b25824ce7d6e5c60c585403551d64e8e3763403d605d79cfc6c5fbe4b4b97ca858b12a0bdb1c16522b74317588521841cf6b1b6424904c8b94d1db8bfdbf63b384abcbb4e2dfadca1188089c0175f7a9d3ca5da2982bee6543e506d8fcd051811bdf22db6b044941ffa462c1c157b0fe698026ff127cc24f1dd8e723d423d505d0b3b997dbdbe48a2b091b779d8ba5963cc47adae92574764712ea8faff0ceb17636f43fc90cfb8316f5b3f1cff0f693aa03abbd9f765d32d21b30d3887e20f637b18e6233f181d0838e6acf7cd2a6bdf

client DH public:

308203243082019706092a864886f70d010301308201880282018100ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff0201020382018500028201802976565126ca39f3fa767d8b7d8c8d104ebb7e5b14a28223cdd5cc5218b800be87d62e7f43216957a1f2e0b21d82ae7cd285a39ab64fe1099ccf6f15e615d6f692870e5710e47eda748f1ec818d58c73673af1546127d97ad7441612b32695c1928a4b9436ea29e9280bbb80cdeaab3a80f729547898f93d686b8b8e3ba40927d0791784f2f255afa8420047e768ac978d664018aef0ac0abbc00825d9f3761cb4550080b5b4c28b20c438593a04084897f1c782a7136c96f718e4d414ecf25200cc04d27f4b660aa4a53440b252d95dd1879857783d0ee4bd9c71cfdf99851d48f803ca987f5251d6d1fa566870f73c854d2a607ae3ebe0fe0a9b5b09fc55c44311270bf207c9d61d51df0a3c41a5f7d528d4bef1a4653a754850297cf17f8b11b01b501a64aca2c776ee92855d3c4409118a71c4a3963aa0d7cbb1e6d3eeb1bf625dfb87a55d19622c9e57a04d6d05dad9e1f0644339237924a14e07b74e965f0c48fe9e9a5a57f1d2de51cfa330c5d6c104fc20901c4a8ea512e0aaacfb19

Error: Supplied key is too large

at DiffieHellmanGroup.dhComputeSecret [as computeSecret] (internal/crypto/diffiehellman.js:113:29)
at exports.challenge (/usr/src/crypto-oracle/controllers/asymmetric.controller.js:150:34)
at Layer.handle [as handle_request] (/usr/src/crypto-oracle/node_modules/express/lib/router/layer.js:95:5)
at next (/usr/src/crypto-oracle/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/usr/src/crypto-oracle/node_modules/express/lib/router/route.js:112:3)
at /usr/src/crypto-oracle/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/usr/src/crypto-oracle/node_modules/express/lib/router/index.js:335:12)
at next (/usr/src/crypto-oracle/node_modules/express/lib/router/index.js:275:10)
at Function.handle (/usr/src/crypto-oracle/node_modules/express/lib/router/index.js:174:3)
GET /asymmetric/dh-challenge/server

令我震惊的是,python客户端生成的公共密钥的长度始终大于服务器端生成的公共密钥的长度。我尝试在客户端上使用PEM编码,但这导致了相同的错误。

不幸的是,不能将DH换成其他密钥交换方法。

javascript python node.js cryptography diffie-hellman
1个回答
0
投票

这里的问题很可能是格式不匹配。 Python代码正在生成一个ASN.1 DER公钥结构,您使用的是十六进制编码。除了公共价值本身之外,该DER结构还包含各种信息,但是node.js端的computeSecret可能只需要公共价值(您应该确认这一点!)。

如果是这种情况,在Python端,该值为y,可以从DHPublicNumbers对象获得。

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