-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Hi, thanks again for the impressive work.
(As a heads up, I hope I didn't miss that this feature was already supported. If that's the case I'm really sorry for the noise)
I was wondering if it would be possible to support exporting a diffie hellman public key in the X9.42 format (as DomainParameters, from X9.42/RFC 3279 sect 2.3.3) format instead of the PKCS#3 format (DHParameter). To give some context, this seems to be supported in OpenSSL (called "DHX"), and there are some mentions of it in cryptography although it seems somewhat unreachable.
Currently, it looks like cryptography supports importing both formats but will only export to the PKCS#3 format. To give an example (the code to reproduce is attached at the very end of this message), I'm importing a SubjectPublicKey under the X9.42 format (DomainParameters) using load_der_public_key and re-exporting it. Here's the Scapy representation before the import:
Algorithm value: 1.2.840.10046.2.1
###[ X509_SubjectPublicKeyInfo ]###
\signatureAlgorithm\
|###[ X509_AlgorithmIdentifier ]###
| algorithm = <ASN1_OID['dhpublicnumber']>
| \parameters\
| |###[ DomainParameters ]###
| | p = 0xffffffffff...ffffffffff <ASN1_INTEGER[3231700607...5361090559]>
| | g = 0x2 <ASN1_INTEGER[2]>
| | q = 0x7fffffffff...ffffffffff <ASN1_INTEGER[1615850303...2680545279]>
| | j = None
| | validationParms= None
\subjectPublicKey\
|###[ DHPublicKey ]###
| y = 0x7b93ec38a6...44f12c77bf <ASN1_INTEGER[1560025493...8064835519]>
After load_der_public_key and public_bytes (as DER + SubjectPublicKeyInfo), I get the following:
Algorithm value: 1.2.840.113549.1.3.1
###[ X509_SubjectPublicKeyInfo ]###
\signatureAlgorithm\
|###[ X509_AlgorithmIdentifier ]###
| algorithm = <ASN1_OID['dhKeyAgreement']>
| \parameters\
| |###[ DHParameter ]###
| | p = 0xffffffffff...ffffffffff <ASN1_INTEGER[3231700607...5361090559]>
| | g = 0x2 <ASN1_INTEGER[2]>
| | l = None
subjectPublicKey= <_Raw_ASN1_BIT_STRING[0000001010...1110111111]=b'\x02\x82\x01\x00{\x93\xec8\xa6\xd3...\xbdOz\x03\x86D\xf1,w\xbf' (0 unused bit)>
My use case is implementing PKINIT in Scapy, which requires https://www.rfc-editor.org/rfc/rfc3279#section-2.3.3, which itself uses the X9.42 format. Currently I'm using a workaround where I recreate the X9.42 structure from the public numbers, so it's not urgent, but I think it would be a nice QoL feature.
Thanks again for the time !
Code to reproduce
from scapy.all import *
conf.color_theme = DefaultTheme() # Enable colors
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import dh
# DER format of a 'dhpublicnumber' SubjectPublicKeyInfo
DATA = bytes.fromhex('308203263082021906072a8648ce3e02013082020c0282010100ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff020102028201007fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d455655347fffffffffffffff0382010500028201007b93ec38a6d3a2e5ea4776f7c942c54f06c334ea637cf45e59c21f6638f6b5baa23420d3229c4a418579db1ce3b956d12ec1bce6883621720f2e596a65dd05881745e7524c88447a5e7a45e149e09f163093088716808e6520a471b53631262a19dc4b3b896717ddca77e15c2d8cf31aa1c03a604834e5f852dc4ac86518f53de4d16101c7f26253973987e1f8c6e8298159ff039646052afe14d634891f57abe5787cb023481aceb65c6ee92b123dfd2ddd15f7dcd733be535d063c4d42a309cb7b84163f8924f88c1b3e400b7f78556ba27d0456b739fe261286cffe7ae404379bc2157bf49fc610e4d46339e0e0a380f8e3b818b0bd4f7a038644f12c77bf')
# Parse a 'dhpublicnumber' from DER
subjectPublicKeyInfo = X509_SubjectPublicKeyInfo(DATA)
print(f"Algorithm value: {subjectPublicKeyInfo.signatureAlgorithm.algorithm.val}")
subjectPublicKeyInfo.show()
# Load it into cryptography
keyinfo = serialization.load_der_public_key(DATA)
# Export as SubjectPublicKeyInfo again
keyasbytes = keyinfo.public_bytes(
encoding=serialization.Encoding.DER,
format=serialization.PublicFormat.SubjectPublicKeyInfo,
)
# Parse again
subjectPublicKeyInfo = X509_SubjectPublicKeyInfo(keyasbytes)
print(f"Algorithm value: {subjectPublicKeyInfo.signatureAlgorithm.algorithm.val}")
subjectPublicKeyInfo.show()