(Erlang) Got error while parsing ecsda public key pem file - erlang

I made private and public keys files as
openssl ecparam -name secp256k1 -genkey -out gen.pem
openssl ec -in gen.pem -pubout -out gen.pub
then I checked .pub file
openssl pkey -in gen.pub -pubin -text -noout
Public-Key: (256 bit)
pub:
04:fc:de:4f:2a:77:bd:c4:f2:74:2b:ba:b5:fc:85:
e4:aa:96:a7:8e:86:14:bc:0d:fa:8e:d2:dd:50:3c:
5d:fa:f4:07:f4:17:80:49:06:19:0c:72:03:63:4e:
07:37:e9:10:64:c8:33:a4:a3:7e:26:d8:df:79:21:
d7:2d:a6:01:80
ASN1 OID: secp256k1
After that start erl
erl
Erlang/OTP 18 [erts-7.2] [source-e6dd627] [64-bit] [smp:3:3] [async-threads:10] [hipe] [kernel-poll:false]
After execution of commands
1>rr(public_key),
{ok,RawData} = file:read_file("gen.pub"),
Decoded = public_key:pem_decode(RawData),
[public_key:pem_entry_decode(X) || X <- Decoded ].
I got exception
** exception error: no match of right hand side value
{error,{asn1,{invalid_length,1}}}
in function public_key:der_decode/2 (public_key.erl, line 229)
I know that there are workarounds, but I'm wondering if I do something wrong or there are errors in public key modules ?
UPD 1.
When we look at result
{ok,#'SubjectPublicKeyInfo'{algorithm = #'AlgorithmIdentifier'{algorithm = {1,2,840,10045,2,1},
parameters = <<6,5,43,129,4,0,10>>},
subjectPublicKey = <<4,241,200,19,168,25,25,81,43,216,
89,201,37,62,66,39,166,231,161,98,
223,133,119,12,...>>}}
we can see next :
{1,2,840,10045,2,1} is oid of ecPublicKey http://oid-info.com/get/1.2.840.10045.2.1
parameters = <<6,5,43,129,4,0,10>>
'OTP-PUB-KEY':decode('EcpkParameters',<<6,5,43,129,4,0,10>>).
gives us
{ok,{namedCurve,{1,3,132,0,10}}}
and
pubkey_cert_records:namedCurves({1,3,132,0,10}).
gives us our source curve - secp256k1, and
subjectPublicKey = <<4,241,200,19,168,25,25,81,43,216,
89,201,37,62,66,39,166,231,161,98,
223,133,119,12,...>>
is public key itself. But this is workaround how I said before.

I tried your steps and it worked for me straight away:
g#crayon2:~/test % openssl ecparam -name secp256k1 -genkey -out gen.pem
g#crayon2:~/test % openssl ec -in gen.pem -pubout -out gen.pub
read EC key
writing EC key
g#crayon2:~/test % openssl pkey -in gen.pub -pubin -text -noout
Public-Key: (256 bit)
pub:
04:f1:c8:13:a8:19:19:51:2b:d8:59:c9:25:3e:42:
27:a6:e7:a1:62:df:85:77:0c:ef:f7:0e:0e:19:93:
df:e6:f5:42:66:7e:ee:02:07:76:85:19:a4:a8:2d:
03:11:73:0c:b2:d4:4c:c7:0e:42:d3:30:b5:51:e3:
97:45:f8:b5:6a
ASN1 OID: secp256k1
g#crayon2:~/test % erl
Erlang/OTP 18 [erts-7.2.1] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V7.2.1 (abort with ^G)
1> rr(public_key).
['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,Data}=file:read_file("gen.pub").
{ok,<<"-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE8cgTqBkZUSvYWcklPkInpuehYt+Fdwzv\n9w4OGZPf5vVCZn7u"...>>}
3> Dec=public_key:pem_decode(Data).
[#'SubjectPublicKeyInfo'{algorithm = <<48,86,48,16,6,7,42,
134,72,206,61,2,1,
6,5,43,129,4,0,10,
3,66,0,4,241,200,
...>>,
subjectPublicKey = not_encrypted}]
My OpenSSL version:
g#crayon2:~/test % openssl version
OpenSSL 1.0.1p-freebsd 9 Jul 2015
System is FreeBSD 10.2-RELEASE. Erlang version is in the shell output above. The gen.pub key that it generated for me (if you want to try to load it) is:
g#crayon2:~/test % cat gen.pub
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE8cgTqBkZUSvYWcklPkInpuehYt+Fdwzv
9w4OGZPf5vVCZn7uAgd2hRmkqC0DEXMMstRMxw5C0zC1UeOXRfi1ag==
-----END PUBLIC KEY-----
Do you maybe want to paste your key so that I can try to load it?
Edit:
Sorry, I missed the last step. This seems to be a bug in the OTP code. The der_decode/2 function is called with KeyType set to ECPoint, see the pem_entry_decode/1 function. But der_decode/2 expects Asn1Type. Calling the 'OTP-PUB-KEY' module directly seems to be working:
8> Bin = hd(Dec)#'SubjectPublicKeyInfo'.algorithm.
32> 'OTP-PUB-KEY':decode('SubjectPublicKeyInfo', Bin).
{ok,#'SubjectPublicKeyInfo'{algorithm = #'AlgorithmIdentifier'{algorithm = {1,
2,840,10045,2,1},
parameters = <<6,5,43,129,4,0,10>>},
subjectPublicKey = <<4,241,200,19,168,25,25,81,43,216,
89,201,37,62,66,39,166,231,161,98,
223,133,119,12,...>>}}
However I am not sure if it returns anything sensible. Maybe worth raising a bug in OTP with the code that you posted in this question as steps to reproduce. Then at least someone competent would verify why it doesn't work. I am sure the steps you followed are fine and the types returned and passed to further functions are OK as far as the documentation is concerned.

I found that lines in public_key.erl ( lines 136-137 )
'ECPoint' ->
der_decode(KeyType, Key0)
have to be replaced with
'ECPoint' ->
{{KeyType,Key0},der_decode('EcpkParameters', Params)}

Related

Problem using P256.Signing.PublicKey on iOS

I generated a public/private key pair using the following commands:
openssl ecparam -genkey -name secp256k1 -noout -out private.pem
openssl ec -in private.pem -text -noout
This generates the following result (don't worry, private key is for testing and not used anywhere)
read EC key
Private-Key: (256 bit)
priv:
4c:b2:38:08:ab:d7:95:eb:38:20:7c:a8:cd:7d:d7:
64:41:17:12:26:d4:77:ce:b7:f8:12:05:15:9e:d2:
dc:0b
pub:
04:ef:01:0e:e3:28:49:e3:ef:bc:52:a7:c6:c5:5d:
96:3c:3e:7c:3f:f9:9b:65:c8:69:76:59:54:16:c2:
31:9c:70:bc:2b:07:a9:fe:c9:26:ed:00:78:72:11:
e1:fb:99:bc:ab:ea:1c:d4:d2:2c:27:a1:06:81:52:
bf:5c:9d:ec:62
The public key is 65 bytes.
Next I export the public key in Base64 format
openssl ec -in private.pem -pubout -out ec-pub.pem
this generates the following file
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE7wEO4yhJ4++8UqfGxV2WPD58P/mbZchp
dllUFsIxnHC8Kwep/skm7QB4chHh+5m8q+oc1NIsJ6EGgVK/XJ3sYg==
-----END PUBLIC KEY-----
However if I do a base64decode of the above key, the result is 88 bytes.
Passing these 88 bytes to P256.Signing.PublicKey(rawRepresentation: data) results in the following error:
CryptoKit.CryptoKitError.incorrectParameterSize
This however, works:
let data = Array<UInt8>(arrayLiteral: 04,0xef,0x01,0x0e,0xe3,0x28,0x49,0xe3,0xef,0xbc,0x52,0xa7,0xc6,0xc5,0x5d,0x96,0x3c,0x3e,0x7c,0x3f,0xf9,0x9b,0x65,0xc8,0x69,0x76,0x59,0x54,0x16,0xc2,0x31,0x9c,0x70,0xbc,0x2b,0x07,0xa9,0xfe,0xc9,0x26,0xed,0x00,0x78,0x72,0x11,0xe1,0xfb,0x99,0xbc,0xab,0xea,0x1c,0xd4,0xd2,0x2c,0x27,0xa1,0x06,0x81,0x52,0xbf,0x5c,0x9d,0xec,0x62)
let key = try P256.Signing.PublicKey(x963Representation: data)
Any idea what I need to do to get this working?
Thanks!
Passing these 88 bytes to P256.Signing.PublicKey(rawRepresentation: data) results in the following error:
There is a PEM prefix, the raw key is at the end, so use instead
P256.Signing.PublicKey(rawRepresentation: data.suffix(65))

openssl key result too small?

I've got a docker that's perpetually in the RESTARTING status if an entrypoint.sh is run.
Checking docker logs, I see many repeats of these 2 chunks of error:
e is 65537 (0x010001)
140680312165760:error:28069065:UI routines:UI_set_result:result too small:../crypto/ui/ui_lib.c:765:You must type in 4 to 1023 characters
140680312165760:error:28069065:UI routines:UI_set_result:result too small:../crypto/ui/ui_lib.c:765:You must type in 4 to 1023 characters
140680312165760:error:0906906F:PEM routines:PEM_ASN1_write_bio:read key:../crypto/pem/pem_lib.c:330:
Generating RSA private key, 2048 bit long modulus
and
e is 65537 (0x010001)
unable to load Private Key
139751600240000:error:28069065:UI routines:UI_set_result:result too small:../crypto/ui/ui_lib.c:765:You must type in 4 to 1023 characters
139751600240000:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:../crypto/evp/evp_enc.c:536:
139751600240000:error:0906A065:PEM routines:PEM_do_header:bad decrypt:../crypto/pem/pem_lib.c:439:
Generating RSA private key, 2048 bit long modulus
My entrypoint.sh has this snippet regarding encryption:
openssl genrsa -des3 -passout pass:x -out /etc/apache2/ssl/pass.key 2048
openssl rsa -passin pass:x -in /etc/apache2/ssl/pass.key -out /etc/apache2/ssl/server.key
cat /tmp/ssl-info.txt | openssl req -new -key /etc/apache2/ssl/server.key -out /etc/apache2/ssl/server.csr
openssl x509 -req -days 365 -in /etc/apache2/ssl/server.csr -signkey /etc/apache2/ssl/server.key -out /etc/apache2/ssl/server.crt
This is a project I've taken over so I'm not fully familiar with this snippet, which is far more verbose than what I typically use to generate and use rsa keys, like in this possibly related thread.
Can anyone please shed some insight into how this error can be solved?
I believe it's an issue with pass:xin line 1, x being only 1 character long.
pass:gsahdg etc should work(gsahdg is a random string).

ruby open ssl api for encrypted key (without nodes option)

On a linux machine with openssl lib installed, when you perform “openssl pkcs12” with “-nodes” option then you get output with unencrypted private key but if you skip the –nodes option then output will have encrypted private key.
e.g.
openssl pkcs12 -in test.pfx -out test.pem
You should see private key encrypted like below
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFDjBABgkqhkiGG7s=
-----END ENCRYPTED PRIVATE KEY-----
How do I achive the above using ruby's open ssl library?
This is how I am generating the private key with ruby:
#private_key = OpenSSL::PKey::RSA.new 2048
#private_key.to_pem.to_s
EDIT:
I guess my question how does this command encrypt the private key:
openssl pkcs12 -in test.pfx -out test.pem
whereas:
“openssl pkcs12 -nodes -in test.pfx -out test.pem"
does not. How do i get the same results using ruby?
There must be something more to this. Perhaps the question needs refined. From what I can tell, you want to print a private key in PEM format. I'm not a ruby programmer but I got this working in about 3 minutes by reading the on ruby-docs.org:
$ cat ssl.rb
require 'openssl'
key = OpenSSL::PKey::RSA.new 2048
cipher = OpenSSL::Cipher.new 'AES-128-CBC'
pass_phrase = 'my secure pass phrase goes here'
key_secure = key.export cipher, pass_phrase
puts key_secure
Choose your cipher and your passphrase and voila, you have encrypted a key with a symmetric cipher:
$ ruby ssl.rb
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,D8062F93C8854E593602D503E1FAC309
UsNQt/Bq7QBldOBU7NW6miCDuC+ODpeplaWQ9BvJW4Wg7j0AbKgMZAn7juegAbjG
JVkpdDNzhs37UVWmqwg64yYP6KEBGg4zCog2a993UHRvFTQb6tyugKHc+uFeyY+D
...
-----END RSA PRIVATE KEY-----
Is there something more you're trying to do?
--
EDIT: The Asker has clarified that the question is about which encryption is used by openssl pkcs12 when not using the -nodes option.
The -nodes option turns off DES encryption. This page shows that the default encryption for private key creation is triple DES, but I don't see the detail there about which DES option. This is also referred to in the manual for man pkcs12. In any case, it's not yet clear to me if you need to know exactly which cipher is used by openssl or if your question is now answered.
You can list ruby's available ciphers like this:
puts OpenSSL::Cipher.cipher
(as specified in the docs)
On my system, quite a few DES ciphers are available with varying parameters:
des
des-cbc
des-cfb
des-cfb1
des-cfb8
des-ecb
des-ede
des-ede-cbc
des-ede-cfb
des-ede-ofb
des-ede3
des-ede3-cbc
des-ede3-cfb
des-ede3-cfb1
des-ede3-cfb8
des-ede3-ofb
des-ofb
des3
desx
desx-cbc
I'm not sure if the PKCS12 spec says which DES cipher should be used or if openssl just has a default. Are you trying to figure out which DES cipher is used by OpenSSL?
I looked a bit further through the openssl wiki and I found references to DES in CBC mode, so I'm guessing that the cipher you are looking for is DES-EDE3-CBC.
Sorry, I guess it's still not completely clear exactly what question you're trying to answer. If what you're trying to do is to find out exactly how openssl is encoding the private key when you don't use -nodes you can see that by cating the file into openssl asn1parse. Maybe this helps: you can start with your rsa private key in plain text as you got it from your ruby program:
$ cat key.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEpA....
-----END RSA PRIVATE KEY
$ cat key.pem | openssl asn1parse
0:d=0 hl=4 l=1188 cons: SEQUENCE
4:d=1 hl=2 l= 1 prim: INTEGER :00
7:d=1 hl=4 l= 257 prim: INTEGER ...
You'll see that this is encoded as an ASN1 SEQUENCE of long integers.
But if you put your key through a roundtrip of pkcs12:
$ openssl pkcs12 -inkey key.pem -out key.pfx -export -nocerts -nodes
(choose a password)
$ openssl pkcs12 -in key.pfx -out outkey.pem -nodes
(enter password)
You'll find your key now wrapped in a new structure, which you can cat to asn1parse:
cat keyout.pem | openssl asn1parse
0:d=0 hl=4 l=1214 cons: SEQUENCE
4:d=1 hl=2 l= 1 prim: INTEGER :00
7:d=1 hl=2 l= 13 cons: SEQUENCE
9:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
You now have an ASN1 rsaEncryption Object with a payload of a large octet string.
Is this what you were trying to learn about? How these values are encapsulated in ASN1?

Get serial number from a certificate using Ruby

Is there a way to know a certificate serial number with Ruby? I know I can get it by using:
openssl x509 -inform DER -in file.cer -noout -serial >"serial.txt"
You can directly run shell commands in ruby and gets its output to a variable. I assume you will have to do something along the line of:
serial = `openssl x509 -inform DER -in file.cer -noout -serial`
Here is a more detailed answer: Calling shell commands from Ruby
There is module OpenSSL in standard library, which includes class OpenSSL::X509::Certificate, with method #serial

Verify return code: 20 (unable to get local issuer certificate) while creating push notification P EM file

I am creating PEM file for Production APNS , and i have done this several time before .
But i am facing an error on terminal while testing my PEm file from below command :
$ openssl s_client -connect gateway.push.apple.com:2195
-cert myCert.pem -key myKey.pem
It gives me :
Verify return code: 20 (unable to get local issuer certificate)
as response.
I have tried so many times but did not identify the problem .
May be it is because of my distribution certificates created on diffrent Mac .
But i am not sure .
Any help suggestion will be helpfull.
The developer link asks to include -CAfile server-ca-cert.pem, which does'nt work either.
All other options of indicating the CAfile gave me errors like 'unable to load certificate'.
The below actually worked for me after trying other options.
openssl s_client -connect gateway.push.apple.com:2195
-cert myCert.pem -key myKey.pem -CAfile entrust_2048_ca.cer
This solution gives 'Verify return code: 0 (ok)'.
On an additional note: You can also specify the .key file as the -key value & it will work too i.e. something like, ref here
openssl s_client -connect gateway.push.apple.com:2195 -cert myCert.pem -key myprivatekey.key -CAfile entrust_2048_ca.cer
You need to give a CA certificate as CAfile commandline argument to s_client. The trusted root certificate for the push servers is the Entrust CA (2048) root certificate which you can download from Entrust's site.
$ openssl s_client -connect gateway.push.apple.com:2195
-cert myCert.pem -key myKey.pem -CAfile entrust_2048_ca.cer
For more information and other possible reasons, please, check Apple developer guide Troubleshooting Push Notifications.

Resources