JSON Web Key (JWK) for IRS E services registration - jwk

While signing up for the IRS E-services they are requesting a JSON Web Key (JWK). they want the following fields in the JWK
kid, kty, use, n, e, x5t, x5c.
The "kty" field should be equal to "RSA".
In this answer it is shown how to generate the keys but I cannot find out how to generate an x5c key.

x5c is fairly simple. you need to remove -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- from the Self-Signed Certificate generated from mkjwk.org
OR
you can use the PHP script: https://control7.net/JWK/generate.php
paste your Public and Private Keypair and Self-Signed Certificate into the textbox and click Go

Related

Meaning of "--_mixed 009J33F94539089U_--" in tail of public key

I have a public key as:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAryQICCl6NZ5gDKrnSztO
3Hy8PEUcuyvg/ikC+VcIo2SFFSf18a3IMYldIugqqqZCs4/4uVW3sbdLs/6PfgdX
7O9D22ZiFWHPYA2k2N744MNiCD1UE+tJyllUhSblK48bn+v1oZHCM0nYQ2NqUkvS
j+hwUU3RiWl7x3D2s9wSdNt7XUtW05a/FXehsPSiJfKvHJJnGOX0BgTvkLnkAOTd
OrUZ/wK69Dzu4IvrN4vs9Nes8vbwPa/ddZEzGR0cQMt0JBkhk9kU/qwqUseP1QRJ
5I1jR4g8aYPL/ke9K35PxZWuDp3U0UPAZ3PjFAh+5T+fc7gzCs9dPzSHloruU+gl
FQIDAQAB
-----END PUBLIC KEY-------_mixed 009J33F94539089U_--
I don't understand what "--mixed 009J33F94539089U--" in the end is, and what it's purpose is.
This key is supposed to be used for creation of encrypted JWT, which is to be sent as payload to hit an API. I used this website to create encrypted JWT, but API hit fails when I use this generated encrypted JWT. But I had to remove this "--mixed 009J33F94539089U--" from my key while entering in the aforementioned website for the creation of encrypted JWT to be successful.
I am wondering if generating encrypted JWT without using this "--mixed 009J33F94539089U--" and using it as payload is causing the API hit to fail. What do I do about this?
[NOTE : The key I mentioned above isn't my actual key.]

Getting the public key exchange

To compute the Client Key Exchange message, what method are we meant to use to encrypt the pre master secret with the server`s public key?
-----BEGIN CERTIFICATE-----
`MII423hasdhashdfxzcvbvwe1209khndasAQWRENWA............
*lots of extra contents*
-----END CERTIFICATE-----
My PreMaster Secret in SHA384(#########################) = random contents
The client key exchange will be the value of *converted value of random contents of SHA384
using ASN1 decoder or is it the .pem that needs to be converted to get client key exchange?

Apple Pay - How to compare merchant public key with publicKeyHash from payment token?

I'm working on Apple Pay payment token decryption.
According to this instruction Payment Token Format Reference on step 2. I need use publicKeyHash field from header of payment token to determine which
merchant certificate was used by Apple.
pulbicKeyHash is SHA–256 hash of the X.509 encoded public key bytes of the merchant’s certificate, Base64 encoded as a string.
I have one merchant certificate. So I assume that if i will take sha-256 hash of my certificate's public key and Base64 encode it i will get the same value that i receive in publicKeyHash field of payment token.
But I can't figure out what particular part of the certificate should I hash.
The initial merchant certificate provided by Apple is in .cer format.
I'have extracted public key from it to .pem format. Than i have tried both take hash -> base64encode of public key (String between -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----) and
to take hash of base64 decoded .pem which i think should be .der and base 64 encode it.
And both failed to match value received from Apple Pay. Also it have different length my base64 encoded hash have 88 char length, and publicKeyHash field is 44 char in length.
When I have tried to base 64 decode publicKeyHash, I've got unreadeble characters like "D��$�f���#c���$����WP��"
But according to Apple documentation there should be sha-256 hash which can not contain such symbols.
Can somebody explain me what concrete steps should I perform in order to complete this merchant certificate check?
In my case the main problem and solution was to use Payment Processing Certificate's public key hash and NOT Merchant Identity Certificate's public key hash, witch I was trying to compare with PublicKeyHash from payment token.
In my excuse I can say that following text from Apple Documentation is pretty much ambiguous:
publicKeyHash SHA–256 hash, Base64 encoded as a string Hash of the
X.509 encoded public key bytes of the merchant’s certificate.
As we have two kind of certificates merchant and payment processing. It was obvious for me that merchant certificate from documentation is merchant id certificate.
Only after re-read Payment Processing certificate description
Payment Processing Certificate. A certificate used to securely
transfer payment data. Apple Pay servers use the payment processing
certificate’s public key to encrypt the payment data. Use the private
key to decrypt the data when processing payments.
from Apple Pay JS documentation I have realized my mistake.
So I hope my experience can help somebody not to step on the same rake)
Its shame I was not able to find openssl command to extract hash directly from the cert. So you have to create the public key first in order to get the public key hash. There are two ways to extract the public key.
Step 1
A. From your ecc private key (payment processing private key)
openssl ec -in ecc_private_key.key -pubout -out ec_public_key.pem
OR
B. From the cert downloaded from apple pay portal (after uploading payment processing csr)
openssl x509 -inform der -in apple_pay.cer -pubkey -noout > apple_pay_public_key.pem
Both will give you public key in following format
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENGbyXUzeZTdeyyNuXyc0nMzXmnLl
xMwd/t/sCZr3RPhytPbZpR/V4/xHqN/MVzozzq30I0/eUefbThEBl236Og==
-----END PUBLIC KEY-----
Step 2
You can use following code to extract the base64 hash from above public key remember to remove headers/footers and line feeds.
I hoped I could have figured out how to use openssl tool to get hash from public key but anyway following c# code works for me. its very simple and easy to port to java/python/php or whatever your preference is. Or just use following code online at ideone.com
String publicKeyBase64 = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENGbyXUzeZTdeyyNuXyc0nMzXmnLlxMwd/t/sCZr3RPhytPbZpR/V4/xHqN/MVzozzq30I0/eUefbThEBl236Og==";
byte[] publicKey = Convert.FromBase64String(publicKeyBase64);
SHA256 sha256 = SHA256Managed.Create();
byte[] hash = sha256.ComputeHash(publicKey);
String publicKeyHash = Convert.ToBase64String(hash);
Console.WriteLine("Result: {0}", publicKeyHash);
Please keep in mind that your system should be able to accept multiple keys at any given time and instead of just verifying you need to load the correct private key based on publicKeyHash you receive from device(iphone/ipad etc) considering the scenario when your current certificate is expiring (or you are revoking for any reason) otherwise your system may not be able to accept the transaction for a short period of time. As per one of my encounter it took apple more than one hour, before new payment processing keys became active, after pressing activate in the portal.
This question and the accepted answer were still a bit vague on details, so here is exact tested method in java to check that token.paymentData.header.publicKeyHash matches Apple Pay Payment Processing Certificate:
private static void checkPublicKeyHash(String publicKeyHash, X509Certificate paymentProcessingCertificate)
throws NoSuchAlgorithmException, CertificateException {
String certHash = Base64.getEncoder().encodeToString(
MessageDigest.getInstance("SHA-256").digest(
paymentProcessingCertificate.getPublicKey().getEncoded()));
if (!Objects.equals(publicKeyHash, certHash)) {
throw new DigestException(String.format(
"publicKeyHash %s doesn't match Payment Processing Certificate hash %s",
publicKeyHash, certHash));
}
}
First it seem the answers to the original question are several months apart. Second all answers seem to lack one critical bit of information; the only reason for step 2 of the the Payment Token Format Reference is that you can have more than one Payment Processing Certificate in use. If you do then apple may use anyone to encrypt the data.
If you have just one Payment Processing Certificate then you can skip this step and just use the its private key. After all, the end result of step two is to get the private key of the payment processing certificate that was used to encrypt the payment data.

Read Base64 private key without encapsulation header in OpenSSL

I am trying to decrypt a message using a private key with openssl. My implementation works fine when i use the private key in the following format
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDDEOX/tFJZrgR0dtTN2/jgPAJjWKE68aw8ayYaGn9fo1sJAE3C
uH6Ym3hu775Enfd5DhtJ38g8RCFLzGVP/LW6n4+LsKS5HRZTGcDkpME0sVoLHLZd
w8z4xZe5h+lT0jwkap5BNyHJCSddipxzjQIEtW+w8V6BkKkFw6UYN1Xn5QIDAQAB
AoGAUeS0Ssfvksrl/+crrElfkPRgpEi/V7nCb5Mkae0Z8JLqUzsXalp+e585zolE
PhZ7oQz1E+ypafPIbsQe/JfByx3itUk7J8+bZO4TpE8n5Afz8EdZLIqJU11MoafH
mWYYWsoMdymgxasuu0ygyeswP42/aw1M+qQgoWBSoPtgLrkCQQDsygWQRI868JKJ
OXzeKV6HTKjGXg37Zm050UaPk2a8inGk6F5RqH1+IZ4istrlcJTpJTuQCsVHJ+SQ
nLveL09vAkEA0uRPeSdXbi92AR/5fj2Xh2APerYjRgK11nh4QEiqbmKyNdW7r9zb
tIQiL9f4AXvcwIVnSWVgiTCwWOa9w8lT6wJBAOMlWPjwC8YqiSeCMjqbzMZVz4Gb
MCZ+N0FDdEC+0csDs8jR78i9rMSWUzBOCpYWzYJp6R1gd6auqh/feojFMZkCQQCO
Gkly2Y+QL2rUVzdGWTpBffjwNsqN4kWkvohIyK4Os3Jh1CMj3S4t9NsUYfI7Dbsx
/rIaQrVJvAUX4mL8Ci0BAkEAuAZBSTmd7MQybVlWCP1AVvlMyW1CV/Mts4tLsGO5
NRMuXY0CrQaO69MW4nuHCSmshBcNB7ahGxYYYMaHmem3QQ
-----END RSA PRIVATE KEY-----
When I try with the same key without the encapsullation headers (-----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY-----) it is failing.
Does these headers are mandatory for the keys?
If I want to use the key without headers which API of OpenSSL should i use?
The type of the key format is defined by the header and footer of the PEM encoded key. Internally it is just a PKCS#1 private key. For more information about the format you can look at this Q/A or the ASN.1 decoded key here.
So although all the information is in the base 64 encoding in the middle implementations may not directly be able to parse it, mainly because the type of the structure is not known.
You can however base 64 decode it and use it as a key within OpenSSL. You may need to specify -inform DER or something similar in that case.

Checking RSA key pairs error

I created a pair of public/private RSA keys by using Elite EL SDK Basic v3.3.2.0 tool. (You can find it here under resources tab. It's free)
Now, I want to check correctness of these pair of RSA keys. As far as I know, I can crate a public key from the private key using the below command, and then compare two public keys if are equal or not(the previous public key and this new publiv key) :
> openssl rsa -in <MyPrivateKey> -out <AnAddressForOutput> -pubout
First of all I convert the format of my private key to base64, using this online tool.
Then I run above command command, but I receive the below error :
I took a look at the private.txt , and this is its contents :
8kP5IpV/oROe6Sb8q5GypqmDCJToHlc2Xbi/sui6/VHu4kaD9pZNJlwP0HVTjyMuQLySzDhPtP8n
xlZeG6jZZPxCMc7na0M+O67z0p5AKoxjELkp4ajiVdjTp0oAYFdkRM782ThA5Hvh+rnt6n++RCZx
HMqa+/dzgG/ONUbI/EMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAc2koT+YAyRpkUR70ZKZNDqAPTf1nirTANUBU8e8
Aa2x9MKh9LZF0usyzkG2td0UkdhluX4cdpw+0jZrbaqw4wZMxpWFyJtzMQtz5lAP0+V8CjR4NIRE
1NPl3ofIqOL9OVp5lW7FkuRwrdhBPhvcmRPpZDZwbBPd1LJ/G/dl0r9B+nn+reo8eKg9XZuk49/c
/w3Gnv2mwMjc/x5wrZ6t48N5xOsZ4oEbAaO0UiUyolEoso4jdp0zrI64cDiXcV3LMfebn/9SRjJ7
3HsQ1PxSFiC9kukafhGcuOLmfclbW3xXpyi8grcIkc529x65QptitGpcOUzDmsybiXXZdFXWObM8
qFSLy4Dve1a5F5s78Be10KE8GZNLdplGUxnYgef8k3cmwASZvMhMgleF2SpE8sCXVSKzc+hyrnFu
A9ZxBtTRw6xxmWUcYmLtzzdzCV+ZaxBFW/96p1Jx7aX2u7x9pNrkF9Y5eonEKCRtkBMZpxAuwWrW
QWrHF3DHBaHuRLNB7z5m+wO716SESJh0TpJA6zBULFkRmG+2F7sHY8hAKgrBvw64iYT8ZkOL4QLT
P0j+qLwh7NCCdj5l8AS7jsN33SU=
As far as I know, every public/private key must have two below lines :
-----BEGIN RSA PRIVATE KEY-----
Private key data
-----END RSA PRIVATE KEY-----
And
-----BEGIN RSA PUBLIC KEY-----
Private key data
-----END RSA PUBLIC KEY-----
Does that mean my tool (Elite EL SDK Basic) doesn't work right? Or I am wrong in one of the above steps?
FYI : This is base64 view of the public key generated with Elite EL SDK Basic :
8kP5IpV/oROe6Sb8q5GypqmDCJToHlc2Xbi/sui6/VHu4kaD9pZNJlwP0HVTjyMuQLySzDhPtP8n
xlZeG6jZZPxCMc7na0M+O67z0p5AKoxjELkp4ajiVdjTp0oAYFdkRM782ThA5Hvh+rnt6n++RCZx
HMqa+/dzgG/ONUbI/EMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQ==
Your key is in a proprietary format. The format is pretty simple though:
1024 bit modulus (always starting with the high bit set
1024 bit public exponent (easily recognized by the leading zero's followed by the fourth number of Fermat, 65537 in binary)
1024 bit private exponent (large number lower than the modulus)
the 5 CRT parameters, all in 512 bit encodings
OpenSSL does not read these kind of private keys. You need to verify your key another way, or create a OpenSSL compatible key from it.
Teaser using your key from import java.security.spec.RSAPrivateCrtKeySpec and import org.bouncycastle.openssl.jcajce.JcaPEMWriter:
$ openssl rsa -check -in somekey.pkcs8.pem
RSA key ok
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDyQ/kilX+hE57pJvyrkbKmqYMIlOgeVzZduL+y6Lr9Ue7iRoP2
lk0mXA/QdVOPIy5AvJLMOE+0/yfGVl4bqNlk/EIxzudrQz47rvPSnkAqjGMQuSnh
qOJV2NOnSgBgV2REzvzZOEDke+H6ue3qf75EJnEcypr793OAb841Rsj8QwIDAQAB
AoGBAM2koT+YAyRpkUR70ZKZNDqAPTf1nirTANUBU8e8Aa2x9MKh9LZF0usyzkG2
td0UkdhluX4cdpw+0jZrbaqw4wZMxpWFyJtzMQtz5lAP0+V8CjR4NIRE1NPl3ofI
qOL9OVp5lW7FkuRwrdhBPhvcmRPpZDZwbBPd1LJ/G/dl0r9BAkEA+nn+reo8eKg9
XZuk49/c/w3Gnv2mwMjc/x5wrZ6t48N5xOsZ4oEbAaO0UiUyolEoso4jdp0zrI64
cDiXcV3LMQJBAPebn/9SRjJ73HsQ1PxSFiC9kukafhGcuOLmfclbW3xXpyi8grcI
kc529x65QptitGpcOUzDmsybiXXZdFXWObMCQDyoVIvLgO97VrkXmzvwF7XQoTwZ
k0t2mUZTGdiB5/yTdybABJm8yEyCV4XZKkTywJdVIrNz6HKucW4D1nEG1NECQQDD
rHGZZRxiYu3PN3MJX5lrEEVb/3qnUnHtpfa7vH2k2uQX1jl6icQoJG2QExmnEC7B
atZBascXcMcFoe5Es0HvAkA+ZvsDu9ekhEiYdE6SQOswVCxZEZhvthe7B2PIQCoK
wb8OuImE/GZDi+EC0z9I/qi8IezQgnY+ZfAEu47Dd90l
-----END RSA PRIVATE KEY-----
To test a private key in PKCS#8 format, the best way to go about this is to use -inform DER instead of converting to base 64.
Base64 is only part of the PEM format. It can requires the headers to be present as well. Sometimes the keys can be concatenated as well. You need to add the headers yourself if you want to verify the private key using PEM.
Also note that OpenSSL already has conversion routines and base64 encoding build in, even on the command line.
As a side note, I don't understand why you want to check the correctness of the output of one single program. If you really want to test correctness, you could think of performing a sign/verify or encrypt/decrypt using the public and private key.

Resources