[erlang-questions] public_key & OpenSSL format weirdness
zxq9
zxq9@REDACTED
Thu Feb 26 02:56:32 CET 2015
I have encountered a strange issue with the public_key and crypto modules
regarding RSA key formats generated by OpenSSL.
If I generate a private key in PEM format, public_key:pem_entry_decode/1 will
not return an #'RSAPrivateKey'{} record, but if I generate the private key in
DER format public_key:der_decode('RSAPrivateKey', KeyFile) will return the
correct #'RSAPrivateKey'{}.
Conversely, if I generate the public key in DER format
public_key:der_decode('RSAPublicKey', PubFile) will give me an asn1 error, but
if I generate the public key in PEM format public_key:pem_entry_decode/1
returns the correct #'RSAPublicKey'{} record.
If I go one step further and decode the public key from a PEM file, then use
public_key:der_encode/2 and write the resulting binary to a file as DER, then
I can use the Erlang-generated DER of the public key with no problem.
The I'm using "OpenSSL 1.0.1f 6 Jan 2014" on Linux.
The following is a screen dump illustrating the problem, then another dump of
some code illustrating the workaround:
%%%%%%%%%%%%%%%%
ceverett@REDACTED:~/Code/erlang/keytest$ cat keygen-der
#! /bin/bash
prefix=${1:?"Cannot proceed without a file prefix."}
keyfile="$prefix"".key.der"
pubfile="$prefix"".pub.der"
openssl genpkey \
-algorithm rsa \
-out $keyfile \
-outform DER \
-pkeyopt rsa_keygen_bits:8192
openssl rsa \
-inform DER \
-in $keyfile \
-outform DER \
-pubout \
-out $pubfile
ceverett@REDACTED:~/Code/erlang/keytest$ cat keygen-pem
#! /bin/bash
prefix=${1:?"Cannot proceed without a file prefix."}
keyfile="$prefix"".key.pem"
pubfile="$prefix"".pub.pem"
openssl genpkey \
-algorithm rsa \
-out $keyfile \
-outform PEM \
-pkeyopt rsa_keygen_bits:8192
openssl rsa \
-inform PEM \
-in $keyfile \
-outform PEM \
-pubout \
-out $pubfile
ceverett@REDACTED:~/Code/erlang/keytest$ ./keygen-der rsa1
.....................................................................................................................................................................................................................................................................................................................
++
.............................................................................................................................................................................................................................................................................
++
writing RSA key
ceverett@REDACTED:~/Code/erlang/keytest$ ./keygen-pem rsa2
..........................................................................................................................................................................................................................................................................................................................................................................................................................
++
........................................................++
writing RSA key
ceverett@REDACTED:~/Code/erlang/keytest$ erl
Erlang/OTP 17 [erts-6.3] [source] [64-bit] [smp:2:2] [async-threads:10]
[kernel-poll:false]
Eshell V6.3 (abort with ^G)
1> rr("/usr/lib/erlang/lib/public_key-0.22.1/include/public_key.hrl").
['AAControls','ACClearAttrs','AccessDescription',
'Algorithm','AlgorithmIdentifier',
'AlgorithmIdentifierPKCS-10','AlgorithmIdentifierPKCS-8',
'AlgorithmIdentifierPKCS5v2-0','AlgorithmIdentifierPKSC-7',
'AlgorithmNull','AnotherName','AttCertValidityPeriod',
'Attribute','AttributeCertificate',
'AttributeCertificateInfo','AttributePKCS-10',
'AttributePKCS-7','AttributeTypeAndValue',
'Attributes_SETOF',
'Attributes_SETOF_valuesWithContext_SETOF',
'AuthorityKeyIdentifier','BasicConstraints',
'BuiltInDomainDefinedAttribute','BuiltInStandardAttributes',
'Certificate','CertificateList','CertificationRequest',
'CertificationRequestInfo',
'CertificationRequestInfo_attributes_SETOF'|...]
2> {ok, DerKeyBin} = file:read_file("rsa1.key.der").
{ok,<<48,130,18,41,2,1,0,2,130,4,1,0,189,228,172,204,135,
175,97,84,205,254,58,197,47,41,196,...>>}
3> DerKey = public_key:der_decode('RSAPrivateKey', DerKeyBin).
#'RSAPrivateKey'{version = 'two-prime',
modulus = 8090848...,
publicExponent = 65537,
privateExponent = 7670114...,
prime1 = 9729823...,
prime2 = 8315513...,
exponent1 = 4754084...,
exponent2 = 6031370...,
coefficient = 4497486...,
otherPrimeInfos = asn1_NOVALUE}
4> {ok, DerPubBin} = file:read_file("rsa1.pub.der").
{ok,<<48,130,4,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,
0,3,130,4,15,0,48,130,4,...>>}
5> DerPub = public_key:der_decode('RSAPublicKey', DerPubBin).
** exception error: no match of right hand side value {error,{asn1,{wrong_tag,
{{expected,2},
{got,16,
{16,
[{6,<<42,134,72,134,247,13,1,1,1>>},{5,<<>>}]}}}}}}
in function public_key:der_decode/2 (public_key.erl, line 219)
6> {ok, PemKeyBin} = file:read_file("rsa2.key.pem").
{ok,<<"-----BEGIN PRIVATE
KEY-----\nMIISQwIBADANBgkqhkiG9w0BAQEFAASCEi0wghIpAgEAAoIEAQCs758ufZpw6gVn\nlcb3GDri0nWovuJ"...>>}
7> [PemKeyData] = public_key:pem_decode(PemKeyBin).
[{'PrivateKeyInfo',<<48,130,18,67,2,1,0,48,13,6,9,42,134,
72,134,247,13,1,1,1,5,0,4,130,18,45,
...>>,
not_encrypted}]
8> PemKey = public_key:pem_entry_decode(PemKeyData).
#'PrivateKeyInfo'{version = v1,
privateKeyAlgorithm = #'PrivateKeyInfo_privateKeyAlgorithm'{
algorithm = {1,2,840,113549,1,1,1},
parameters = <<5,0>>},
privateKey = [48,130,18,41,2,1,0,2,130,4,1,0,172,239,159,46,
125,154,112,234,5,103,149,198,247|...],
attributes = asn1_NOVALUE}
9> {ok, PemPubBin} = file:read_file("rsa2.pub.pem").
{ok,<<"-----BEGIN PUBLIC
KEY-----\nMIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEArO+fLn2acOoFZ5XG9xg6\n4tJ1qL7iUiVxLzWM"...>>}
10> [PemPubData] = public_key:pem_decode(PemPubBin).
[#'SubjectPublicKeyInfo'{algorithm = <<48,130,4,34,48,13,
6,9,42,134,72,134,
247,13,1,1,1,5,0,3,
130,4,15,0,48,130,
...>>,
subjectPublicKey = not_encrypted}]
11> PemPub = public_key:pem_entry_decode(PemPubData).
#'RSAPublicKey'{modulus = 7368345...,
publicExponent = 65537}
%%%%%%%%%%%%%%%%
The PEM -> DER workaround for the public key:
%%%%%%%%%%%%%%%%
ceverett@REDACTED:~/Code/erlang/keytest$ cat keygen-asym
#! /bin/bash
prefix=${1:?"Cannot proceed without a file prefix."}
keyfile="$prefix"".key.der"
pubfile="$prefix"".pub.pem"
openssl genpkey \
-algorithm rsa \
-out $keyfile \
-outform DER \
-pkeyopt rsa_keygen_bits:8192
openssl rsa \
-inform DER \
-in $keyfile \
-outform PEM \
-pubout \
-out $pubfile
ceverett@REDACTED:~/Code/erlang/keytest$ ./keygen-asym rsa3
............++
..............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
++
writing RSA key
ceverett@REDACTED:~/Code/erlang/keytest$ erl
Erlang/OTP 17 [erts-6.3] [source] [64-bit] [smp:2:2] [async-threads:10]
[kernel-poll:false]
Eshell V6.3 (abort with ^G)
1> {ok, PubPemBin} = file:read_file("rsa3.pub.pem").
{ok,<<"-----BEGIN PUBLIC
KEY-----\nMIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEAyqeCmfJNxPynjp8RDUWU\nKaEyLIrwv1WLfkmy"...>>}
2> [PubPemData] = public_key:pem_decode(PubPemBin).
[{'SubjectPublicKeyInfo',<<48,130,4,34,48,13,6,9,42,134,
72,134,247,13,1,1,1,5,0,3,130,
4,15,0,48,130,...>>,
not_encrypted}]
3> Pub1 = public_key:pem_entry_decode(PubPemData).
{'RSAPublicKey',8634564...,65537}
4> PubDer = public_key:der_encode('RSAPublicKey', Pub1).
<<48,130,4,10,2,130,4,1,0,202,167,130,153,242,77,196,252,
167,142,159,17,13,69,148,41,161,50,44,138,...>>
5> file:write_file("rsa3.pub.der", PubDer).
ok
6> {ok, PubDerBin} = file:read_file("rsa3.pub.der").
{ok,<<48,130,4,10,2,130,4,1,0,202,167,130,153,242,77,196,
252,167,142,159,17,13,69,148,41,161,50,...>>}
7> Pub2 = public_key:der_decode('RSAPublicKey', PubDerBin).
{'RSAPublicKey',8634564...,65537}
8> Pub1 = Pub2.
{'RSAPublicKey',8634564...,65537}
9> {ok, KeyDerBin} = file:read_file("rsa3.key.der").
{ok,<<48,130,18,40,2,1,0,2,130,4,1,0,202,167,130,153,242,
77,196,252,167,142,159,17,13,69,148,...>>}
10> Key = public_key:der_decode('RSAPrivateKey', KeyDerBin).
{'RSAPrivateKey','two-prime',
8634564...,
65537,
5179789...,
9406113...,
9179736...,
8502631...,
7664604...,
4453412...,
asn1_NOVALUE}
11> TestMessage = <<"A test message.">>.
<<"A test message.">>
12> Sig = public_key:sign(TestMessage, sha512, Key).
<<129,61,138,16,14,168,75,66,38,125,157,33,233,114,150,
135,45,97,237,181,2,255,162,180,242,124,36,223,208,...>>
13> public_key:verify(TestMessage, sha512, Sig, Pub2).
true
14> public_key:verify(TestMessage, sha512, Sig, Pub1).
true
%%%%%%%%%%%%%%%%
What is going on here?
More information about the erlang-questions
mailing list