Pavisa
Pavisa

Reputation: 162

Diffie-Hellman key exchange between Python and Node fails with error Supplied key is too large

I'm trying to do a DH key exchange between the Python 3.6 client and the Node server running in Docker container with the latest node image (Node version: v13.10.1).

I'm using cryptography.io (2.9.2) library on the python client side. The client generates DH keys and sends the hex-encoded public key to the server. Here's the code snippet:

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)

The server uses crypto library to compute the secret based on the DH key that was received. Here's the code snippet:

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);
    ...
}

I logged both public keys just to compare the structure, I don't expect them to be the same obviously. The output is something along the lines of:

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

What strikes me is that the length of the public key generated by the python client is consistently larger than the one that is generated on the server-side. I tried using PEM encoding on the client-side but that resulted in the same error.

Swapping DH for some other key exchange method is unfortunately not an option.

Upvotes: 2

Views: 975

Answers (1)

Paul Kehrer
Paul Kehrer

Reputation: 14089

It's very likely that the issue here is a mismatch in formats. The Python code is generating an ASN.1 DER public key structure, which you're hex encoding. That DER structure contains a variety of information in addition to the public value itself, but it's likely that computeSecret on the node.js side wants just the public value (you should confirm this!).

If that's the case, on the Python side that value is y and can be obtained from the DHPublicNumbers object.

Upvotes: 5

Related Questions