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
In Apple's documentation for the keys available for a Wallet pass, there's an option for a dictionary for NFC-related data. I understand that use of this key requires special permission from Apple. Regardless ...
message is straight forward -- it's the data passed to a NFC terminal (usually a unique identifier for the customer).
encryptionPublicKey, however, has me confused. Apple states it is the public encryption key used by the Value Added Services protocol. Use a Base64 encoded X.509 SubjectPublicKeyInfo structure containing a ECDH public key for group P256.
Can anyone explain what this second sentence means and/or what a developer would have to do to generate this? From what would one even generate the public/private keys?
You'll need the following to generate the public and private key. The private key is used by the merchant hardware when reading the pass and decoding the payload.
The compressed public key is what goes into your pass.json.
openssl ecparam -name prime256v1 -genkey -noout -out nfcKey.pem
openssl ec -in nfcKey.pem -pubout -out nfcPubkey.pem -conv_form compressed
cat nfcPubkey.pem
Outputs:
-----BEGIN PUBLIC KEY-----
MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgAC/Bu9nyAtG1DQe7t7jszLb+dZ1GbX
oR8G0rIXoak67NM=
-----END PUBLIC KEY---
You'll need Base64 key (without the newline) for the encryptionPublicKey field.
E.g.
MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgAC/Bu9nyAtG1DQe7t7jszLb+dZ1GbXoR8G0rIXoak67NM=
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
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.
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