Delphi Lockbox 3 DOES NOT load public key generated by OpenSSL - delphi

Trying to load RSA public key in Delphi by the use of Lockbox 3 I encounter this error: "(Error) Public key file corrupt, empty or the wrong type."
I have generated a pair of public and private key by OpenSSL using the following commands:
openssl genrsa -out private.pem 2048 //generate private key
openssl rsa -pubout -in private.pem -out public.pem //generate public key
Then in Delphi I used the following code to load libeay32.dll:
sig: TOpenSSL_Signatory;
...
Sig.Clear;
Sig.isLoaded := True;
if Sig.isLoaded then ShowMessage('The OpenSSL library libeay32.dll was loaded successfully.');
which always loads successfully.
Then I use the below code to load the public key (i.e. public.pem):
f:=TFileStream.Create('c:\keys\public.pem', fmOpenRead);
sig.LoadKeysFromStream(f, [partPublic]);
f.Free;
The above code results in the following error:
"(Error) Public key file corrupt, empty or the wrong type."
How can I solve this problem and load the public key generated by OpenSSL successfully to Delphi?
The public.pem is shown below:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz98tqhhArIOoTtO3HFDW
TcQz4EcSBIc3YejV9GPQq+gMdqO5VsmQhOfHyWAMwOVJ49w/fGib+zyIPmocwCqE
jnQ5UjpNhkO5JIDmlf5NZGI2JcuORg+4Anqgo0D4YGCY04w7Sk8dArLHK+PThPwC
uM2XqyRCpcyTsWRKcH5/G6k6OBBhj5kIeNOy+ZCLeADhNUNiEBXdHQWoMbC+x8Fk
E73KzoOg61BQ7HBMJmfK2p8Shi/wEqD1DPJK3IKkTS+KAB8LvLXdUTDHg1O6FbDn
FfSQWYXzV5MWZR7M3POyX6rjoGRFK+v3mG08S5qEPj/l/PBgNL6wI/aBNkFsYxgf
7QIDAQAB
-----END PUBLIC KEY-----

Method TOpenSSL_Signatory.LoadKeysFromStream() is expecting the key to end in ...
-----END RSA PUBLIC KEY-----
This method expects the key to be in PEM (SSLeay) format. SSLeay PEM has base64 content tagged with -----BEGIN/END RSA PUBLIC/PRIVATE KEY-----.
To generate a key in the traditional PEM format see ...
https://superuser.com/questions/606215/openssl-pkcs8-default-format-gives-rsa-private-key
http://rietta.com/blog/2012/01/27/openssl-generating-rsa-key-from-command/
You can't change the format simply by renaming the header/footer. You actually have to generate SSLeay PEM by passing the correct options to OpenSSL.

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))

Decrypt PKCS#8 Ruby OpenSSL

I need to use the OpenSSL ruby gem to decrypt a file. I've tried what every post told me to do. I've tried using this code from: Load PKCS#8 binary key into Ruby
def box(tag, lines)
lines.unshift "-----BEGIN #{tag}-----"
lines.push "-----END #{tag}-----"
lines.join("\n")
end
def der_to_pem(tag, der)
box tag, Base64.strict_encode64(der).scan(/.{1,64}/)
end
pem = der_to_pementer code here('ENCRYPTED PRIVATE KEY', File.read('./file.key'))
key = OpenSSL::PKey::RSA.new(pem, 'passkey')
puts key
puts pem
And I get this:
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAzxy...
...ECYUOVC3zgw23aGcFA8z9ghI=
-----END RSA PRIVATE KEY-----
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFDjBABgk...
...Y948X9Zop7aCnxmWI7vHNts=
-----END ENCRYPTED PRIVATE KEY-----
But I need something like this:
-----BEGIN PRIVATE KEY-----
MIIEvwIBADA...
...ZwUDzP2CEg==
-----END PRIVATE KEY-----
This is the console code that works, but as I said I need to use the ruby gem:
openssl pkcs8 -inform DER -in "./file.key" -passin pass:passkey -out "./file.key.pem"
Unfortunately, there is no way to decrypt on PKCS#8 format by openssl gem. But there are some hacky ways.
Execute the OpenSSL command from ruby.
Install the following gem (https://github.com/twg/openssl_pkcs8)

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?

Difference between csr created from linux openssl v/s ruby openssl library

What is the difference between csr created from linux openssl v/s ruby openssl library:
openssl req -out mytest.csr -new -newkey rsa:2048 -nodes -keyout
mytest.
The public key created from above looks something like this:
-----BEGIN CERTIFICATE REQUEST-----\nMIIC2jCCAcICAQAwgZQxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNRDEWMBQGA1UE\nBwwNU2lsdmVyIFNwcmluZzELMAkGA1UECgwCTUwxCzAJBgNVBAsMAkVTMR8wHQYD\nVQQDDBZtc2NsaWVudDI4LnNhbXRlc3QuY29tMSUwIwYJKoZIhvcNAQkBFhZtc2Ns\naWVudDI4QHNhbXRlc3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\nAQEAvMJwLZp9w/YPZz31+ZyozD5S3Xb1Jjtdx0VBUrRuDKi4y+XRlzOeHHvRiSZJ\nVMI2LLLta0Zel4ULK4vSoP2OH5ezQbAGUslxePupFFulPZUJJrNLVZJ/9jNOgKoI\n6tu+8TGP2UivOGfW5OQFYLFLZJad/PP7IoAOoYB79lqnE/+3/vjys5eHL6dOZ/0I\nmUj8G5jw1thZlOQpA4Es2Xoxnvkr1kiJpoa+4s8L6kX2PLRCoWmP1ZqQ1pi3oHoP\n6kLo/qQ2KiIrPcrDGi5aGtKkCrj64JAS4IIcLiBvI+KXNCzaB6f2I7ChBEkA8iEU\nSe2LqqSs0eumBFH0HwE4uvwOWQIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAJZI\niySQfZpFYL7SZWWvUxdHPxmwrw3PdcPSAJZQImoMNCSFC0kCtIzl+LleZN8/WzkV\nQ2Ps6cg3+bSWrJ+gA6EjcA4X8oGHN545snaOUf/ZRXf0mKbtu+U3asTiaE8Dz8P6\n5gz81GaA+ZDmjwk7ezrz6+gED439M5sot5yaeH8EfD5c49y0hOP9gg1VDJMNiwsf\nVARrIu+eHCPi2PXzBXZTPdivzn3cZQU0vsu91DzuHHXzCQv5wYE/iVh5lyWjLeFS\nFg5m4mLOtjKRzPeCpldkGkFRssvOoBOixZHPainzUHKk7eVNggXPjgFa4fk3uPp0\nWUftUDM5l7ANFqv5ii0=\n-----END
CERTIFICATE REQUEST-----
However when i try to create it from ruby's open ssl library:
irb(main):004:0> private_key = OpenSSL::PKey::RSA.new 2048
irb(main):005:0> private_key.public_key.to_pem
=> "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAqDaG8Je5YY2kXM6w/a7uiTTAsJd1JwkP7w44licoYxn7N+sYuv3K\n2iFAfumP3NEWueeRcCPSiGD3BpCKwxo4tch9uOFGOuaWYiK9XC7OOZV755+hix0S\nWph45bwiOSQX0Jr6SB6T7RBXxAF7RFdMVfo4AyZkakVaMxr0lVO8E7RqO6WaeYV2\ne6GYU2BPy60U7iXVK+15RGMQIWaiUt5iCGzJqBn+IE1GQJpytbRg7melx4e6zPQf\n5Aa4Wufm7SFEVMJ5/rzTALOZa5VWlPRhb7luxYXXLDqckB8/6Bok6kpu5qkJjHHz\nwRabh7u8Vy6cRuz+Df7LTsRuamkZLG8KXQIDAQAB\n-----END
RSA PUBLIC KEY-----\n"
The above public key is much smaller.
What is different between the 2?
How can i make ruby's open ssl generate a csr & private like linux openssl.
Looking at your other question as well, it appears that your fundamental misunderstanding is that you think that a CSR is a public key. A CSR does indeed contain a public key, but it includes additional data (e.g. subject and signature) and is a distinct type of object.
You started off right with creating the RSA key pair, but you then have to generate the CSR. You can do it like this:
require 'openssl'
# Create public/private key pair.
key = OpenSSL::PKey::RSA.new 2048
print key.to_pem()
print key.public_key.to_pem()
# Create CSR.
request = OpenSSL::X509::Request.new
request.subject = OpenSSL::X509::Name.parse 'C=US/CN=foobar'
request.public_key = key.public_key
request.sign(key, OpenSSL::Digest::SHA256.new)
print request.to_pem()
Note that ruby can't prompt you for the subject fields, so you have to specify them via the API.

jclouds with GCE Cannot connect: -----END RSA PRIVATE KEY----- doesn't contain % line [-----END ]

Trying to use google-compute-engine provider for jclouds there appears to be a problem when putting the pem extracted from the .p12 into the credential section of my jenkins config.xml
Followed these instruction https://github.com/jclouds/jclouds-labs-google/tree/master/google-compute-engine to extract the pem file from the p12
Error is see when trying to test connection:
Cannot connect to specified cloud, please check the identity and credentials: chars -----BEGIN RSA PRIVATE KEY----- HIDDEN -----END RSA PRIVATE KEY----- doesn't contain % line [-----END ]
If I remove the "-----BEGIN RSA", jclouds correctly tells me that % doesnt contain the line -----BEGIN
but it seems to be barfing on parsing the "-----END" part
I thought It might have to do with pasting the key into the Credential section of the configure jenkins U/I,
but I placed the key directly into the config.xml's section, and I'm getting the same error.
jenkins-1.583-1.1.noarch with Jclouds plugin 2.8
Any ideas?
-Aric
Convert the p12 file into pem format (it will ask for the keystore password, which is usually "notasecret"):
openssl pkcs12 -in my_keystore.p12 -out my_keystore.pem -nodes
Extract only the pk and remove passphrase
openssl rsa -in my_keystore.pem -out my_key.pem
Then you can use this key and problem will be solved.
The solution on my side is to use the Textarea. FYI: JENKINS-25283
and reason is losing the new line character. Hope this help you.
I was having a similar problem after reading the key from a user interface.
The fix for me was:
privatekey = privatekey.replace("\\\n", System.lineSeparator());
This ensures the key includes system specific line-break characters.

Resources