如何使用密码学在 Python 中使用 Kotlin PublicKey 对象加载编码的 public 密钥
How to load encoded public key using Kotlin PublicKey object in Python using cryptography
我目前在加载从 Python 中的 Kotlin“提取”的 public 键时遇到问题。我正在尝试在 Kotlin 和 Python 之间创建功能性 X25519 EDH,因此我需要加载 Python 中由 Kotlin 代码创建的 public 密钥。反之亦然。
我的 Kotlin 代码如下所示
class EllipticDiffieHellman {
private val keyPairGenerator = KeyPairGenerator.getInstance("XDH")
private val parameters = NamedParameterSpec("X25519")
private val keyAgreement = KeyAgreement.getInstance("XDH")
private val keyFactory = KeyFactory.getInstance("XDH")
fun generateKeyPair() : KeyPair {
keyPairGenerator.initialize(parameters)
return keyPairGenerator.generateKeyPair()
}
fun getKeyShare(keyPair: KeyPair) : ByteArray = keyPair.public.encoded
fun bytesToPubKey(keyShare: ByteArray) : PublicKey = keyFactory.generatePublic(X509EncodedKeySpec(keyShare))
fun getSharedKey(keyPair: KeyPair, keyShare: PublicKey) : ByteArray {
keyAgreement.init(keyPair.private)
keyAgreement.doPhase(keyShare, true)
return keyAgreement.generateSecret()
}
}
...
val EDH = EllipticDiffieHellman()
val keypair_python = EDH.generateKeyPair()
File("keyshare_kotlin").writeBytes(EDH.getKeyShare(keypair_python))
当我尝试使用 bytesToPubKey
加载相同的 ByteArray 时,一切正常。
现在我的 Python 代码(一部分):
import cryptography.hazmat.primitives.serialization as serialization
with open("keyshare_kotlin", "rb") as f:
keyshare_kotlin = f.read()
loaded_public_key = serialization.load_der_public_key(keyshare_kotlin)
这行不通。我一直在尝试使用其他 cryptography
的加载函数,但 none 有效。
我得到 ValueError: Could not deserialize key data. The data may be in an incorrect format or it may be encrypted with an unsupported algorithm.
感谢您的帮助。
我找到了一个可行的解决方案,尽管如评论中所述 - 它不是最优的。
Kotlin/Java 生成的字节与 Python 生成的字节使用不同的 header。 Kotlin 的 header 是 14 个字节长,而 Python 的 header 是 12 个字节长。这是编码 public 键的这两个“版本”之间的唯一区别,虽然 Python 能够加载 12 字节 header,但无法加载 Kotlin 的 14 字节 header.
使用从使用密码学 .public_key().public_bytes(serialization.DER, serialization.SubjectPublicKeyInfo)
编码的字节中提取的 header 并用它替换 Kotlin 生成的 header 可以在 Python 中加载编码字节。
import cryptography.hazmat.primitives.asymmetric.x25519 as x25519
import cryptography.hazmat.primitives.serialization as serialization
private_key = x25519.X25519PrivateKey.generate()
public_bytes = private_key.public_bytes(
encoding=serialization.Encoding.DER,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
with open("keyshare_kotlin", "rb") as f:
keyshare_kotlin = f.read()
loaded_keyshare = serialization.load_der_public_key(public_bytes[:12] + keyshare_kotlin[14:])
我目前在加载从 Python 中的 Kotlin“提取”的 public 键时遇到问题。我正在尝试在 Kotlin 和 Python 之间创建功能性 X25519 EDH,因此我需要加载 Python 中由 Kotlin 代码创建的 public 密钥。反之亦然。
我的 Kotlin 代码如下所示
class EllipticDiffieHellman {
private val keyPairGenerator = KeyPairGenerator.getInstance("XDH")
private val parameters = NamedParameterSpec("X25519")
private val keyAgreement = KeyAgreement.getInstance("XDH")
private val keyFactory = KeyFactory.getInstance("XDH")
fun generateKeyPair() : KeyPair {
keyPairGenerator.initialize(parameters)
return keyPairGenerator.generateKeyPair()
}
fun getKeyShare(keyPair: KeyPair) : ByteArray = keyPair.public.encoded
fun bytesToPubKey(keyShare: ByteArray) : PublicKey = keyFactory.generatePublic(X509EncodedKeySpec(keyShare))
fun getSharedKey(keyPair: KeyPair, keyShare: PublicKey) : ByteArray {
keyAgreement.init(keyPair.private)
keyAgreement.doPhase(keyShare, true)
return keyAgreement.generateSecret()
}
}
...
val EDH = EllipticDiffieHellman()
val keypair_python = EDH.generateKeyPair()
File("keyshare_kotlin").writeBytes(EDH.getKeyShare(keypair_python))
当我尝试使用 bytesToPubKey
加载相同的 ByteArray 时,一切正常。
现在我的 Python 代码(一部分):
import cryptography.hazmat.primitives.serialization as serialization
with open("keyshare_kotlin", "rb") as f:
keyshare_kotlin = f.read()
loaded_public_key = serialization.load_der_public_key(keyshare_kotlin)
这行不通。我一直在尝试使用其他 cryptography
的加载函数,但 none 有效。
我得到 ValueError: Could not deserialize key data. The data may be in an incorrect format or it may be encrypted with an unsupported algorithm.
感谢您的帮助。
我找到了一个可行的解决方案,尽管如评论中所述 - 它不是最优的。
Kotlin/Java 生成的字节与 Python 生成的字节使用不同的 header。 Kotlin 的 header 是 14 个字节长,而 Python 的 header 是 12 个字节长。这是编码 public 键的这两个“版本”之间的唯一区别,虽然 Python 能够加载 12 字节 header,但无法加载 Kotlin 的 14 字节 header.
使用从使用密码学 .public_key().public_bytes(serialization.DER, serialization.SubjectPublicKeyInfo)
编码的字节中提取的 header 并用它替换 Kotlin 生成的 header 可以在 Python 中加载编码字节。
import cryptography.hazmat.primitives.asymmetric.x25519 as x25519
import cryptography.hazmat.primitives.serialization as serialization
private_key = x25519.X25519PrivateKey.generate()
public_bytes = private_key.public_bytes(
encoding=serialization.Encoding.DER,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
with open("keyshare_kotlin", "rb") as f:
keyshare_kotlin = f.read()
loaded_keyshare = serialization.load_der_public_key(public_bytes[:12] + keyshare_kotlin[14:])