使用 Python 生成 Java 兼容的 Diffie-Hellman
Generate a Java compatible Diffie-Hellman using Python
我正在尝试重写 Python 中的以下代码。原始代码是使用 sjcl 库在 Javascript 中编写的。
// Inputs
var serverPubX = "WIUBDotrk02Rk/apL11jQPbmX0quyaYz2EIkGUlVf7s=";
var serverPubY = "diZ2CbfSUy5Kr82OIfd4Ajusq2K+/kjGZ7ymcqVwn2k=";
// The code
var serverPubXBits = sjcl.codec.base64.toBits(serverPubX);
var serverPubYBits = sjcl.codec.base64.toBits(serverPubY);
var serverPubKeyPointBits = serverPubXBits.concat(serverPubYBits);
var serverPubKey = new sjcl.ecc.elGamal.publicKey(
sjcl.ecc.curves.c256, serverPubKeyPointBits);
var clientKeys = sjcl.ecc.elGamal.generateKeys(256, 1);
// What I need:
var sharedKey = clientKeys.sec.dhJavaEc(serverPubKey);
我的主要问题是 dhJavaEc
功能。根据 sjcl 文档,它是 Java compatible Diffie-Hellmann function。但是我在 pycryptodome 库中找不到任何等效的东西。
我检查了 dhJavaEc
代码,这是它的作用:
// Looks like it converts the server key to Jacobian and then multiply it by client key
serverPubKey.J.toJac().mult(clientKeys.sec.I, serverPubKey.J).toAffine().x.toBits()
// serverPubKey.J is the X and Y keys concatenated:
sjcl.codec.base64.fromBits(serverPubKey.J.toBits())
"WIUBDotrk02Rk/apL11jQPbmX0quyaYz2EIkGUlVf7t2JnYJt9JTLkqvzY4h93gCO6yrYr7+SMZnvKZypXCfaQ=="
// In my example, clientKeys.sec.I is this:
sjcl.codec.base64.fromBits(clientKeys.sec.I.toBits())
"zIhDVlFUpWQiRP+bjyEIhSLq8rcB8+XInXGhm6JGcVI="
// And the calculated key is:
sjcl.codec.base64.fromBits(sharedKey)
"ZBin/RV1qnfKoIuel+5fzv1y8rn3UZkMPO3pXva3VzQ="
如何使用 Python 生成等效的“sharedKey”?
PyCryptodome目前似乎不支持ECDH,见Future plans. An alternative is the Cryptography library, see Elliptic Curve Key Exchange algorithm.
库期望私钥为 int,public 未压缩格式的密钥为 bytes object。未压缩格式由串联的 x 和 y 坐标组成,前面是 0x04 字节。
sjcl.ecc.curves.c256
定义 secp256r1(又名 prime256v1 又名 NIST P-256 ).
然后在 Python 中使用 密码学 的可能实现是:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec
import base64
curve = ec.SECP256R1()
clientKey = 'zIhDVlFUpWQiRP+bjyEIhSLq8rcB8+XInXGhm6JGcVI='
privateKeyInt = int.from_bytes(base64.b64decode(clientKey), byteorder='big', signed=False)
privateKey = ec.derive_private_key(privateKeyInt, curve, default_backend())
serverPubKey = 'WIUBDotrk02Rk/apL11jQPbmX0quyaYz2EIkGUlVf7t2JnYJt9JTLkqvzY4h93gCO6yrYr7+SMZnvKZypXCfaQ=='
publicKeyUncomp = b'\x04' + base64.b64decode(serverPubKey)
publicKey = ec.EllipticCurvePublicKey.from_encoded_point(curve, publicKeyUncomp)
sharedSecret = privateKey.exchange(ec.ECDH(), publicKey)
print(base64.b64encode(sharedSecret).decode('utf8')) # ZBin/RV1qnfKoIuel+5fzv1y8rn3UZkMPO3pXva3VzQ=
生成与 JavaScript 代码相同的共享密钥。
我正在尝试重写 Python 中的以下代码。原始代码是使用 sjcl 库在 Javascript 中编写的。
// Inputs
var serverPubX = "WIUBDotrk02Rk/apL11jQPbmX0quyaYz2EIkGUlVf7s=";
var serverPubY = "diZ2CbfSUy5Kr82OIfd4Ajusq2K+/kjGZ7ymcqVwn2k=";
// The code
var serverPubXBits = sjcl.codec.base64.toBits(serverPubX);
var serverPubYBits = sjcl.codec.base64.toBits(serverPubY);
var serverPubKeyPointBits = serverPubXBits.concat(serverPubYBits);
var serverPubKey = new sjcl.ecc.elGamal.publicKey(
sjcl.ecc.curves.c256, serverPubKeyPointBits);
var clientKeys = sjcl.ecc.elGamal.generateKeys(256, 1);
// What I need:
var sharedKey = clientKeys.sec.dhJavaEc(serverPubKey);
我的主要问题是 dhJavaEc
功能。根据 sjcl 文档,它是 Java compatible Diffie-Hellmann function。但是我在 pycryptodome 库中找不到任何等效的东西。
我检查了 dhJavaEc
代码,这是它的作用:
// Looks like it converts the server key to Jacobian and then multiply it by client key
serverPubKey.J.toJac().mult(clientKeys.sec.I, serverPubKey.J).toAffine().x.toBits()
// serverPubKey.J is the X and Y keys concatenated:
sjcl.codec.base64.fromBits(serverPubKey.J.toBits())
"WIUBDotrk02Rk/apL11jQPbmX0quyaYz2EIkGUlVf7t2JnYJt9JTLkqvzY4h93gCO6yrYr7+SMZnvKZypXCfaQ=="
// In my example, clientKeys.sec.I is this:
sjcl.codec.base64.fromBits(clientKeys.sec.I.toBits())
"zIhDVlFUpWQiRP+bjyEIhSLq8rcB8+XInXGhm6JGcVI="
// And the calculated key is:
sjcl.codec.base64.fromBits(sharedKey)
"ZBin/RV1qnfKoIuel+5fzv1y8rn3UZkMPO3pXva3VzQ="
如何使用 Python 生成等效的“sharedKey”?
PyCryptodome目前似乎不支持ECDH,见Future plans. An alternative is the Cryptography library, see Elliptic Curve Key Exchange algorithm.
库期望私钥为 int,public 未压缩格式的密钥为 bytes object。未压缩格式由串联的 x 和 y 坐标组成,前面是 0x04 字节。
sjcl.ecc.curves.c256
定义 secp256r1(又名 prime256v1 又名 NIST P-256 ).
然后在 Python 中使用 密码学 的可能实现是:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec
import base64
curve = ec.SECP256R1()
clientKey = 'zIhDVlFUpWQiRP+bjyEIhSLq8rcB8+XInXGhm6JGcVI='
privateKeyInt = int.from_bytes(base64.b64decode(clientKey), byteorder='big', signed=False)
privateKey = ec.derive_private_key(privateKeyInt, curve, default_backend())
serverPubKey = 'WIUBDotrk02Rk/apL11jQPbmX0quyaYz2EIkGUlVf7t2JnYJt9JTLkqvzY4h93gCO6yrYr7+SMZnvKZypXCfaQ=='
publicKeyUncomp = b'\x04' + base64.b64decode(serverPubKey)
publicKey = ec.EllipticCurvePublicKey.from_encoded_point(curve, publicKeyUncomp)
sharedSecret = privateKey.exchange(ec.ECDH(), publicKey)
print(base64.b64encode(sharedSecret).decode('utf8')) # ZBin/RV1qnfKoIuel+5fzv1y8rn3UZkMPO3pXva3VzQ=
生成与 JavaScript 代码相同的共享密钥。