I'm trying to use the openssl library to implement RSA encryption / decryption using a public and private key. I think I could resume what I'm trying to do with converting this C code to nim: http://hayageek.com/rsa-encryption-decryption-openssl-c/
I'm unable to properly load my public and private key using openssl:
var rsa: PRSA
var public_key: string = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRQHDdjYg59eEGUzfFhe1k4J4n
FKsFMJAyL/K1qmURJ8ecnBJNpAzAuSc19ncFLsCNjP9DL/oIQO42+3Z9Wc3d5GMB
XheYOdu5+5/l+0RIt3Z2fC1E/jugLW9ThAJsmYG42u4bbQq1TEsgSyzcydO13UPy
+FC6ovs+pRBY02sH6QIDAQAB
-----END PUBLIC KEY-----"""
var bio = BIO_new_mem_buf(addr publickey, -1)
rsa = PEM_read_bio_RSA_PUBKEY(bio, rsa.addr, nil, nil)
if rsa.isNil:
echo "ERROR: Could not load PUBLIC KEY! PEM_read_bio_RSA_PUBKEY FAILED"
echo ERR_error_string(ERR_get_error(), nil)
This gets me the error:
ERROR: Could not load PUBLIC KEY! PEM_read_bio_RSA_PUBKEY FAILED
error:0909006C:PEM routines:get_name:no start line
I have the same error when I try loading the private key.
I have also tried loading the keys from files, but no luck there either... Would really appreciate if someone could give me a tip there, as I really don't understand what's going on, and the documentation on Nim interaction with openssl is extremely scarce to say the least...
PS: something is wrong with the registration on this forum... Had to make a second account with a temp email because I never received the confirmation email on my real email address (yes, I checked spams). Someone might want to take a look a this....
Ah, quite a simple mistake, or rather two small mistakes, both easily made. The OpenSSL wrapper is just a very thin wrapper around the C library, this means that it isn't really aware of Nims types and needs a little bit of extra help. When you write addr publickey that is the address of the Nim string object. This object is essentially the same as a seq[char] and holds the length and capacity of the string, and then a reference to the string data itself. Since you want a pointer to the C-compatible string data you need to use addr publickey[0] which will be a pointer to the first character of the actual string (which is what a string or char * in C is).
The second mistake is within your string literal """ will preserve whitespace, including the spaces used for indentation. So you need to unindent the public key literal for this snippet to work. The following code snippet fixes both issues and works as expected:
import openssl
var rsa: PRSA
var public_key: string = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRQHDdjYg59eEGUzfFhe1k4J4n
FKsFMJAyL/K1qmURJ8ecnBJNpAzAuSc19ncFLsCNjP9DL/oIQO42+3Z9Wc3d5GMB
XheYOdu5+5/l+0RIt3Z2fC1E/jugLW9ThAJsmYG42u4bbQq1TEsgSyzcydO13UPy
+FC6ovs+pRBY02sH6QIDAQAB
-----END PUBLIC KEY-----"""
var bio = BIO_new_mem_buf(addr publickey[0], -1)
rsa = PEM_read_bio_RSA_PUBKEY(bio, rsa.addr, nil, nil)
if rsa.isNil:
echo "ERROR: Could not load PUBLIC KEY! PEM_read_bio_RSA_PUBKEY FAILED"
echo ERR_error_string(ERR_get_error(), nil)