How to use erlang public_key:decrypt_private? - erlang

I try to encrypt text with public RSA key and decrypt this text using a private RSA key. When I encrypt user public key it works.
encode public_key
encrypt_public_key(PlainText, PublicKey) ->
[ RSAEntry2 ] = public_key:pem_decode(PublicKey),
PubKey = public_key:pem_entry_decode( RSAEntry2 ),
public_key:encrypt_public(PlainText, PubKey).
But when I try to decrypt this text using a private key, it does not work, and I don't know why.
decode private key
decrypt_private_key(CryptText,PrivateKey) ->
[ RSAEntry2 ] = public_key:pem_decode(PrivateKey),
PrivKey = public_key:pem_entry_decode( RSAEntry2 ),
Result = public_key:decrypt_private(CryptText, PrivKey, rsa_pkcs1_padding ),
Result.
How i encode and try to decode
PublicKey = ems_util:open_file(?SSL_PATH ++ "/" ++ binary_to_list(<<"public_key.pem">>)),
CryptoText = ems_util:encrypt_public_key(ResponseData2,PublicKey),
PrivateKey = ems_util:open_file(?SSL_PATH ++ "/" ++ binary_to_list(<<"private_key.pem">>)),
%erro in this line
TextPlain = ems_util:decrypt_private_key(TextCrypt,PrivateKey).
Error
=ERROR REPORT==== 17-Mar-2017::10:59:29 ===
Ranch listener ems_http_server1, connection process <0.2159.0>, stream 1 had its request process <0.2160.0> exit with reason function_clause and stacktrace [{public_key,decrypt_private,[<<55,66,78,123,456,2456>>,<<55,173,2367,140,71>>,asn1_NOVALUE}],[{file,"public_key.erl"},{line,313}]},{ems_util,decrypt_private_key,2,[{file,"src/util/ems_util.erl"},{line,614}]},{ems_auth_user,do_barer_authorization,1,[{file,"src/auth/ems_auth_user.erl"},{line,51}]},{ems_dispatcher,lookup_request,1,[{file,"src/distpatcher/ems_dispatcher.erl"},{line,70}]},{ems_http_handler,init,2,[{file,"src/http/ems_http_handler.erl"},{line,22}]},{cowboy_handler,execute,2,[{file,"src/cowboy_handler.erl"},{line,39}]},{cowboy_stream_h,execute,3,[{file,"src/cowboy_stream_h.erl"},{line,172}]},{cowboy_stream_h,proc_lib_hack,3,[{file,"src/cowboy_stream_h.erl"},{line,157}]}]
I don't know what's happening.

I describle the solution for my problem. The problem is the public and the private keys are generated wrongly. The right way to generate a pair key rsa using openssl is:
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
These commands generate a correct key pair and the code now ir working correctly.

Related

Unable to upload CSR/Certificates to the Open Banking Directory

I have this error showing when I attempt to upload a Certificate request to the Open Banking Directory as an OB Signing certificate.
When I copy the message, I am given this message;
When I inspect the network requests, it seems to show an Internal Server Error (Response 500) and returns graphql. This is the response:
{"errors":[{"message":"Error: Request failed with status code 400","locations":[{"line":2,"column":3}],"path":["addCertificate"]}],"data":null}
Has this issue occurred with anyone before? I generated the CSR with Open SSL with my credentials with this command:
openssl req -new -newkey rsa:2048 -nodes -out [STATEMENT_CLIENT_ID].csr -keyout [STATEMENT_CLIENT_ID].key -subj "/C=GB/ST=/L=/O=OpenBanking/OU=[ORGANISATION_ID]/CN=[STATEMENT_CLIENT_ID]" -sha256
The tags in braces are redacted. I have also tried docker but to no gain. I'm all ears to any solutions which come my way.
Thank you for your time.
Solved this by generating a CSR on OpenSSL with the corresponding config files. eiDAS formatting is essential.
Commands:
req -new -config "obseal.cnf" -out "Seal.csr" -keyout "SealPrivateKey.key"
req -new -config "obwac.cnf" -out "WAC.csr" -keyout "WACPrivateKey.key"
Per BenTaylor's question above, OBWAC and OBSEAL have a hidden gem in their make up in the form of QCStatements that map the roles specified in a Software Statement Assertion to the roles that the resultant certificates from a CSR have specified in their qcStatement OID. Here's an example of a CNF for OBSEAL:
[ req ]
default_bits = 2048
encrypt_key = no
default_md = sha256
default_keyfile = obseal.key
utf8 = yes
string_mask = utf8only
prompt = no
distinguished_name = client_dn
req_extensions = client_reqext
[ client_dn ]
countryName = "GB"
organizationName = "Typical O name"
# Subject common name
commonName = "<Open Banking Directory Org ID>"
[ client_reqext ]
keyUsage = critical,digitalSignature,nonRepudiation
subjectKeyIdentifier = hash
qcStatements=DER:30713013060604008e4601063009060704008e46010602305a06060400819827023050303930110607040081982701020c065053505f504930110607040081982701030c065053505f414930110607040081982701040c065053505f49430c0c4f70656e2042616e6b696e670c0547422d4f42
If you paste the above binary code into an ASN1 decoder, you'll see the following structure emerge:
SEQUENCE (2 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 0.4.0.1862.1.6
SEQUENCE (1 elem)
OBJECT IDENTIFIER 0.4.0.1862.1.6.2
SEQUENCE (2 elem)
OBJECT IDENTIFIER 0.4.0.19495.2
SEQUENCE (3 elem)
SEQUENCE (3 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 0.4.0.19495.1.2
UTF8String PSP_PI
SEQUENCE (2 elem)
OBJECT IDENTIFIER 0.4.0.19495.1.3
UTF8String PSP_AI
SEQUENCE (2 elem)
OBJECT IDENTIFIER 0.4.0.19495.1.4
UTF8String PSP_IC
UTF8String Open Banking
UTF8String GB-OB
The nodes PSP_* map OBWAC/OBSEAL certificates to software statement roles in what appears to be the following manner:
PSP_PI = PISP
PSP_AI = AISP
PSP_IC = CBPII
You can use an ASN1 editor to edit/delete nodes and derive the binary as required for both OBWAC and OBSEAL. Just bang in the binary minus the qcStatement=DER: part and be done with it. You can view the structure of the qcStatement using this web site too.
Another note is that unlike an eIDAS QSeal cert, the maximum key length for an OBSEAL seems to be 2048 bits.
Hopefully someone will find this useful as UK banks start to discard the old Open Banking signing/transport keys and implement eIDAS/OBWAC+SEAL instead. Good luck and let the fun begin. o7
I have the same problem at the moment in production sandbox and the open banking is not showing any relevant errors.
Using OpenSSL version: OpenSSL 1.1.1g 21 Apr 2020
And following this here which pops up over the upload field.
And following this pdf link for documentation which pops up over the upload field.
[ req ]
default_bits = 2048
encrypt_key = yes
default_md = sha256
utf8 = yes
string_mask = utf8only
prompt = no
distinguished_name = client_dn
req_extensions = client_reqext
[ client_dn ]
countryName = "GB"
organizationName = "My bank Ltd"
organizationIdentifier = "OBGBR-GB-Unknown1315H25731lXE8ZIEM"
commonName = "Unknown1315H25731lXE8ZIEM"
[ client_reqext ]
keyUsage = critical,digitalSignature,nonRepudiation
subjectKeyIdentifier = hash
qcStatements=DER:3081813013060604008e4601063009060704008e46010603306a06060400819827023060303930110607040081982701010c065053505f415330110607040081982701020c065053505f504930110607040081982701030c065053505f41490c1b46696e616e6369616c20436f6e6475637420417574686f726974790c0647422d464341
The differences that i can see is with the definition of organizationIdentifier. In the docs they show how to define it if using tool that does not support it but the current version of OpenSSl does support it. So when printed with:
openssl asn1parse -in obwac.csr -inform PEM
Example in pdf:
66:d=5 hl=2 l= 3 prim: OBJECT :2.5.4.97
71:d=5 hl=2 l= 34 prim: UTF8STRING :PSDGB-OB-Unknown1315H25731lXE8ZIEM
New version of OpenSSL:
66:d=5 hl=2 l= 3 prim: OBJECT :organizationIdentifier
71:d=5 hl=2 l= 34 prim: UTF8STRING :OBGBR-GB-Unknown1315H25731lXE8ZIEM

DER Encoding Public Key created by cryptopp is different then openssl

I've been trying to create a DER encoded public key using an RSA private key. The way I normally create it is using the command line:
openssl rsa -pubout -outform DER -in ~/.keys/api_key.pem -out der_pub.der
When I use CryptoPP to create this file, they are slightly different. It seems it has an extra section. The one created by openssl has a little extra section. I'm assuming this is the BIT STRING mentioned in the CryptoPP API. https://www.cryptopp.com/docs/ref/class_r_s_a_function.html
void DEREncodePublicKey (BufferedTransformation &bt) const
encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
This is what my code looks like:
...
CryptoPP::RSA::PrivateKey rsaPrivate;
rsaPrivate.BERDecodePrivateKey(queue, false /*paramsPresent*/, queue.MaxRetrievable());
CryptoPP::ByteQueue bq;
rsaPrivate.DEREncodePublicKey(bq);
CryptoPP::FileSink fs1("cryptopp_pub.der", true);
bq.TransferTo(fs1);
CryptoPP::RSA::DEREncodePublicKey encodes subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
Try CryptoPP::RSA::PublicKey::DEREncode. Being careful to apply this to only the public key, as RSA::PrivateKey does overload the DEREncode method.
Here I'm using CryptoPP 8.2
Load DER encoded private key from disk
CryptoPP::RSA::PrivateKey private_key;
{
CryptoPP::FileSource file{"my.key", true};
private_key.BERDecodePrivateKey(file, false, -1);
}
Save out DER encoded public key
CryptoPP::FileSink sink{"my.pub", true};
CryptoPP::RSA::PublicKey{private_key}.DEREncode(sink);
OpenSSL:
# generate a new RSA private key (DER format)
openssl genrsa | openssl rsa -outform DER -out my.key
# hash/fingerprint the public key
openssl rsa -in my.key -inform DER -pubout -outform DER | openssl sha256
writing RSA key
362945ad4a5f87f27d3db3b4adbacaee0ebc3f778ee2fe76ef4fb09933148372
# compare against hash of our code sample's generated public key
cat my.pub | openssl sha256
362945ad4a5f87f27d3db3b4adbacaee0ebc3f778ee2fe76ef4fb09933148372
As another example; if we want CryptoPP to generate a SHA256 fingerprint:
std::string hash_out_str;
{
CryptoPP::SHA256 sha256;
CryptoPP::HashFilter filter{
sha256,
new CryptoPP::HexEncoder{
new CryptoPP::StringSink{hash_out_str}
}
};
CryptoPP::RSA::PublicKey{private_key}.DEREncode(filter); // intentionally slice to ensure we aren't exposing a public key
filter.MessageEnd();
}
std::cout << hash_out_str << '\n';
Outputs:
362945AD4A5F87F27D3DB3B4ADBACAEE0EBC3F778EE2FE76EF4FB09933148372
i.e., we need to copy/slice to a RSA::PublicKey to invoke the OpenSSL compatible DER encoding method

Load RSA private key generated by openssl to MacOS SecKeyRef fails

I am working on a project that needs to read a RSA private key (DER format) into a MacOS's SecKeyRef object.
I generate the key by
openssl genrsa -out private.pem 1024
openssl rsa -in private.pem -outform DER -out private.der
I load the private.der to MacOS by using SecKeyCreateWithData:
unsigned char *keyBytes; // contains all the bytes from the file "private.der"
int keyBytesLen; // length of the data loaded
NSData keyData = [NSData dataWithBytes:keyBytes length:keyBytesLen];
NSDictionary* options = #{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
(id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
(id)kSecAttrKeySizeInBits: #1024};
SecKeyRef privateKey = SecKeyCrecateWithData((__bridge CFDataRef) keyData, (__bridge CFDictionaryRef) options, &error);
OSstatus status = SecKeyDecrypt(privateKey, .... some encrypted message);
// status returns -50 (errSecParam)
So I notice the privateKey is loaded successfully, but it fails to decrypt the encrypted message. I am 100% sure other parameters I have put into SecKeyDecrypt() function is correct because it works if I generate the privateKey by macOS's built-in function rather than loading from a DER-format file generated by openssl.
I also notice that when I dump the key (binary format), the first few bytes (version header) is different from the key generated by MacOS's built-in function and openssl. If the key is generated by MacOS (ex: SecKeyGeneratePair) and outputed by SecKeyCopyExternalRepresentation, the first few bytes look like:
3082 025d 0201 0002 8181 ...
while the key generated by openssl looks like:
3082 025c 0201 0002 8181 ...
I know (based on PKCS#1) that these bytes represent the "version" of the private key but not sure how to interpret it.
Any help or similar working example to load key generated by openssl to MacOS's API will be appreciated

How can I build the Apple APNS v2 specific OID into the CSR

Apple APNS V2 introduce the "topic" concept, and assign a customized OID for it and give out an example:
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html#//apple_ref/doc/uid/TP40008194-CH11-SW1
Extension ( 1.2.840.113635.100.6.3.6 )
Critical NO
Data com.yourcompany.yourexampleapp
Data app
Data com.yourcompany.yourexampleapp.voip
Data voip
Data com.yourcompany.yourexampleapp.complication
Data complication
How can I build this extension into the CSR. I know I need to edit the openssl.conf to add it in the "req" section, but what's the specific codes to put all these attributes into CSR? The following command I try can add one line into the CSR, but how can I add the following part? Thanks in advance!!!
[ customized_extension ]
1.2.840.113635.100.6.3.62=Critical NO,ASN1:UTF8String:1.2.840.113635.100.6.3.62
1.2.840.113635.100.6.3.62=ASN1:UTF8String:com.yourcompany.yourexampleapp
???? --How to add the next part?
openssl req -new -sha256 -key ses_lab_20170120.key -out ses_lab_20170120.csr -config openssl.cnf
openssl req -in ses_lab_20170120.csr -text -noout
Certificate Request:
Data:
Version: 0 (0x0)
Subject: C=CN, ST=GD, L=GZ, O=Ericsson, OU=SES, CN=test
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:b0:9e:2f:3d:52:da:71:0a:e3:93:13:2b:c4:92:
4b:4b:3c:0c:70:98:d5:6d:3f:a0:af:f4:03:d0:26:
53:6a:d4:7e:82:d7:95:6a:8f:29:eb:88:6c:67:4a:
94:d4:b5:ed:9a:b5:d4:e4:44:8c:1d:21:ec:ba:03:
df:61:3f:6a:5e:c0:ea:13:00:62:e0:df:3c:39:2b:
1a:2b:b0:b5:39:1a:bf:ba:d5:85:0d:37:bd:2a:92:
d1:6e:9b:05:37:bf:bf:c2:83:ca:8f:27:5a:b3:d3:
b5:53:17:7e:b0:d8:ea:ec:51:09:7f:d5:e7:5e:a5:
03:ff:63:28:da:11:5a:ae:10:01:05:46:da:62:02:
b2:20:4d:08:a8:47:ed:95:2a:b9:f3:e9:f5:e6:fb:
b0:29:99:c5:cf:d3:80:98:8b:8a:10:4f:8a:fa:57:
f8:50:31:e7:02:6a:8c:16:13:99:1d:e3:6d:ce:d5:
43:d9:c9:1f:50:b8:55:07:00:88:d6:ab:b1:44:46:
32:62:03:25:91:9a:ae:72:09:b8:a4:07:9c:86:95:
bf:59:0e:0e:65:73:b7:0f:86:d3:d2:7e:ac:7e:82:
9f:61:c8:41:b0:d6:25:2a:4f:09:93:6d:6a:15:b8:
60:22:ba:34:d4:69:dc:b1:6c:98:8a:4a:01:31:71:
b8:0f
Exponent: 65537 (0x10001)
Attributes:
Requested Extensions:
1.2.840.113635.100.6.3.62:
..com.yourcompany.yourexampleapp
Signature Algorithm: sha256WithRSAEncryption
62:53:2f:85:1f:7c:9f:4c:b8:48:c0:df:20:5d:3a:6d:f3:55:
7c:63:90:66:3c:14:d5:e0:c8:4e:f3:21:2d:d8:5b:ed:4c:2d:
38:5b:90:ad:a6:e4:0c:1d:e7:b6:c6:66:1f:41:c9:cf:f1:10:
13:a7:27:bf:f5:74:93:76:dd:e0:1a:64:7e:66:62:87:9b:e4:
88:c2:74:65:fc:90:04:d3:24:51:2b:c3:f0:ef:0d:b3:e9:cb:
d8:23:d6:63:31:0a:93:d6:f3:36:99:8d:1e:33:fd:fd:c3:6d:
a8:38:9d:63:ce:2b:2b:4e:43:93:77:87:05:e7:c5:6d:39:98:
f2:7d:39:3e:bc:a9:9a:59:c4:ce:c2:88:ef:95:67:55:cc:a9:
e4:3a:8a:1d:49:66:77:81:8d:0e:9b:ce:f1:cc:3d:83:62:cc:
86:fe:4a:2d:f0:b9:70:9f:d8:75:9e:52:99:53:4e:ea:32:8d:
af:11:9c:d3:cc:d4:8b:e5:24:c2:10:2b:11:61:52:2d:a3:67:
f0:f6:9c:8e:3e:12:66:0f:14:9e:1c:3d:77:81:3a:26:35:e0:
15:c5:ab:d2:4b:51:c4:2e:7d:7b:0a:92:ae:89:fb:f2:fa:32:
81:52:da:49:16:c3:84:a9:82:e1:2d:b6:9b:03:ae:88:fb:fd:
17:ee:3c:1b

Reading Private Key in PEM format with LockBox

I have to digitally sign a string using the SHA-1 algorithm with RSA using PKCS#1 padding. I have downloaded Turbo Power Lockbox.
The private key I have is in PEM format and was created using openssl:
openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj
"/C=US/ST=CA/L=Mountain View/CN=www.mycompany.com"
-keyout myrsakey.pem -out c:\temp\myrsacert.pem
Here is what it looks like:
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDFzvqdAEQn9MrSLTNua5SOxshV/8jQIf3qpfunBXa9SVdm4NJw
lY7iYpwivw7EdMlBe4FmezN9LGwyIokcUSt4KUdWmA8l4Lm5rcuDzzfmlVWP7y+j
0GKG2XCp2JwHpW4Q5WiMgcAnCMD/gbDustfz3utxQhLNBdWp2MlrEH2/rQIDAQAB
AoGAUMZmnHohWtehgxYmLG8N6QfPgx7CWAupbop9KwUWKdGrOT2RcZwBDv0JmT6/
vwWZsX3Hp5ujuPfM7uQfbUrQHrcruUg/fPY8YXcWgNfOytGpaN/XKxfy2g2Cp8mE
4yoDR2QW8jo25ZH1q1cJ3jMyX9xlXaSZm7qtaoiDydE6roECQQDxqtP2tMEZ2FmQ
2o4T5Zv7P4II2PrLq+9IP0ASCZ2VzLxm2Pk6kxjnPjZ2oHG8pUQHvMz0m8Br3BY8
X1BpXrj9AkEA0YpBH7qm/nbG6YjxKAL3PbxXUJ06T/ByLjfstfCrT3LxDeklfWJb
n/V8ahRcKPLajdbKAuWvJA5NvjeJPi34cQJAZ+vD1nUIDKsiaM3zBs9X8gTvUAqu
XmMDNJguXxNPdplh8wAevHeA3/+6v+xivHJ8/K7Nm+pWJouv7Co4k/ctqQJASV4y
TUzKmgC2xyCG5+6Z6Ujf/b7/ouva3un//PiG0yu40ZkX4l4lHM4UwQPd/QyDj/Rs
CTWo7GQBvp+tc1MfUQJBALnQnNOIIkvwIK+1J6iLZgh7GurbCPMrH8nSn8SxkfBe
qq5JWo31LQAUNDW5ntG0qHZQpx6zm2MzIlt2NgOLf4s=
-----END RSA PRIVATE KEY-----
If I am not mistaken, the component I want to use is TLbRSAKey. So I have tried to create key object and read it from file:
var
mPrivateKey: TLbRSAKey;
begin
mPrivateKey := TLbRSAKey.Create(aks1024);
mPrivateKey.LoadFromFile('C:\temp\myrsakey.pem');
On the LoadFromFile I get a "Invalid RSA Key" error. What am I doing wrong? Does Lockbox support keys in PEM format? None of the examples illustrate; everything seems to be in ASN format
I am not a delphi programmer, but I thought I'd try to provide some pointers.
First, make sure you generate a new private key for your real application. Now that you've shared your private key with us, we wouldn't want any open security holes out there.
Secondly, the ASN.1 format is generated using the DER output from OpenSSL. The PEM format is just the base-64 encoding of the binary ASN.1 structure (and the markers are added).
You can get back to DER in one of two ways:
1) You can parse and decode the base-64 data in the PEM envelope. To do this, just decode the data between the -----BEGIN/END RSA PRIVATE KEY----- markers.
Or, since you are creating a new key anyway... ;)
2) You could use the -outform DER argument when you generate your key using OpenSSL.
I'm not certain this will work for your application, but maybe it will help get you a little further.
TIP to convert a PEM provate key to DER format, use the rsa utility in OpenSSL:
openssl rsa -inform PEM -outform DER -in privkey.pem -out privkey.der

Resources