Apple Wallet NFC encryptionPublicKey - ios

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=

Related

secp256k1 private key save to pem file

Hi I am doing the save private key of secp256k1 to pem file with Swift.
As I generate the private key, I got a 32 bytes key, somehow in base64 it is "7vInO7T/GBg6bxkr+6W4ESV4UOy6W4E2N4i9fBgMqYM=" which is a quite short string.
I see some example of other private key generated by other languages such as PHP or Scala I can see the private key in PEM file is somehow like this:
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIEEtespOtpvBZFfn+2YX/9WlsRLTb8YSWkfV1IBP+Lz9oAcGBSuBBAAK
oUQDQgAEun8ex7Yei3nN1mnw2/c9QNwIEzAZ8+upXkN5hgHNgrpn2ufxP8G/byc9
Lx8wKQIXhmCIXMySxUeQUCDzl65trA==
-----END EC PRIVATE KEY-----
Which is a very long string of base64.
How can I generate such long string and what the rule for it? I mean what should I do to make my quite short base64 string that I can generate to such long string as other languages do?

How to Generate JWT token apple connect iOS

I'm trying to generate a JWT token for Apple Connect but It's look like something is missing in the "Verify signature" field.
From the API Apple Store Connect dashboard, I'm only able to download the "private key" name AuthKey_{kid}.p8.
From https://jwt.io/, I select the "ALGORITHM" as "ES256" then two field appears in the "SIGNATURE" section :
a) Public key or certificate
b) Private key or certificate (AuthKey_{kid}.p8)
Issue :
- I do have the "Invalid Signature" message displaying ...
- I don't have any idea where to find the "Public key or cerficate"
I'm following these docs :
- https://developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests
- https://medium.com/xcblog/generating-jwt-tokens-for-app-store-connect-api-2b2693812a35
Do you have any idea how to fix find the "Public key"?
Thank you for your help,
The .p8 file includes the private and public keys. You need to extract those using OpenSSL.
To get the private key:
$ openssl ec -in AuthKey.p8 -out AuthKey_private.p8
To get the public key:
$ openssl ec -in AuthKey.p8 -pubout -out AuthKey_public.p8
Using keys generated via these commands got the signature verified on jwt.io.

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

SWCrypt public key VS PKCS8PEM Key

I want to user SWCrypt for RSA encryption and decryption. i should send my public key base64 decoded to server. but when i try send generated public key base64 i can't get this error in server side:
let (privateKey, publicKey) = try CC.RSA.generateKeyPair(2048)
let publicKeyBase64 = publicKey.base64EncodedString()
error: java.security.InvalidKeyException: IOException: algid parse error, not a sequence
but when send PEMPublicKey getting successfully response.
let publicKeyPEM = SwKeyConvert.PublicKey.derToPKCS8PEM(publicKey)
what is difference between publicKeyBase64 and publicKeyPEM?
sample of generated key:
MIIBCgKCAQEAuWwCZpNXJtT2spBsDwrQaTFGVAjicM341Qzg+1whtlj9J60c/7HYe6AcGHa8Dinkiuk7Whs1Wpa34aa223WQsa+kFSNwkC6oDUXhewan3VEsv1uedzHc8JPlTXnItJsP8cIETFgHpdKWk462hU09mVCTtQTix0BEb8snS96wERvKq957OeaGtFasfT/bQfY0mbDu6eEMqswmfX8j84kuTfwWtqt6mLMTJaDwnsGc5WY1zkau68IQ/CBiiLpZ5hSVMs2pPj3Ao0+wNhR5MlMgdcwrU62SHWcMJ5cYssFgWZyZSvO3n/yW43fE5a1i+9Tm2trveGIdMR4d/MoA79/8IQIDAQAB
sample of generated PEM key :
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuWwCZpNXJtT2spBsDwrQaTFGVAjicM341Qzg+1whtlj9J60c/7HYe6AcGHa8Dinkiuk7Whs1Wpa34aa223WQsa+kFSNwkC6oDUXhewan3VEsv1uedzHc8JPlTXnItJsP8cIETFgHpdKWk462hU09mVCTtQTix0BEb8snS96wERvKq957OeaGtFasfT/bQfY0mbDu6eEMqswmfX8j84kuTfwWtqt6mLMTJaDwnsGc5WY1zkau68IQ/CBiiLpZ5hSVMs2pPj3Ao0+wNhR5MlMgdcwrU62SHWcMJ5cYssFgWZyZSvO3n/yW43fE5a1i+9Tm2trveGIdMR4d/MoA79/8IQIDAQAB
how can send generated public key simple of PEM key format?
thanks.
X509 is a standard for Public Key Infraestructure, not a encoding format. You can encode a X509 public key in PEM (base64), DER(binary) or XML. Also the binary data of the public key can be represented in PCKS#1 or X509 SubjectPublicKeyInfo.
In my knowledge PKCS#8 is a standard for private keys. See PKCS #8: Private-Key Information Syntax Standard. So I guess SWCrypt is really using X509 SubjectPublicKeyInfo (Maybe i have not read some RFCs), which is what your server is waiting for.
let publicKeyPEM = SwKeyConvert.PublicKey.derToPKCS8PEM(publicKey)
SubjectPublicKeyInfo encapsulates the public key into a ASN.1 structure adding a header. If you encode the raw data of the public key (DER) using publicKey.base64EncodedString, that header is not added and your server does not know how to manage it.

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