What is the file with .p8 extension? (APNs Auth Key / JWT) - ios

I think it is a little ridiculous but it's hard to find information about what is this file. I've found a lot info how to get this Apple Push Notification Authentication Key, but i also want to know exactly what is it.
Here is some info i have found:
Benefits:
No need to re-generate the push certificate every year;
One auth key
can be used for all your apps;
Same for sandbox and Production.
From Apple Docs:
Token-based provider connection trust: A provider using the
HTTP/2-based API can use JSON web tokens (JWT) to provide validation
credentials for connection with APNs. In this scheme, you provision a
public key to be retained by Apple, and a private key which you retain
and protect. Your providers then use your private key to generate and
sign JWT provider authentication tokens. Each of your push
notification requests must include a provider authentication token.
You can use a single, token-based connection between a provider and
APNs can to send push notification requests to all the apps whose
bundle IDs are listed in your online developer account.
Every push notification request results in an HTTP/2 response from
APNs, returning details on success or failure to your provider.
Further check Token-Based Provider-to-APNs Trust section.
Questions:
What is actually the .p8 file?
What programm can open it? (Keychain didn't work for me)
Is there a way to convert it to .pem or .p12?
A little flow-out question in order to not create a new topic: Does the server side operate with .p8 the same way as .p12 or it should be additional tools added?

The following is the state of my research:
The APNS .p8 file contains the PRIVATE KEY that is used to SIGN the JWT content for APNS messages.
The file itself is a pure text file, the KEY inside is formatted in PEM format.
The part between the -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY----- is a base64 formatted ASN.1 PKCS#8 representation of the key itself. Some can use the following web service to extract its contents (ASN1JS).
The KEY itself is 32 bytes long and is used to create the required ECDSA P-256 SHA-256 signature for the JWT. The resulting JWT looks like this '{JWT header base64 encoded}.{JWT payload base64 encoded}.Signature (64 bytes) base64 encoded'.
There are a lot of web services to decode such tokens, but some couldn't check the signature, as the corresponding PUBLIC KEY isn't known (Apple keeps it secret when providing the PRIVATE KEY).
EDIT: It seems, that the PUBLIC KEY is also included in the .p8 file, it can be extracted via OpenSSL (and is visible when decoding the ASN.1 content: the 520 bit stream).
openssl ec -in AuthKey_123ABC4567.p8 -pubout -out
AuthKey_123ABC4567_Public.p8

File extensions are just a convention, but most likely the .p8 extension is used to indicate that it is a PKCS#8 PrivateKeyInfo (or EncryptedPrivateKeyInfo).
I'd expect the Keychain program to be able to open it as "a key", but not having a mac at hand I can't say. It should open with SecItemImport (kSecFormatOpenSSL, kSecItemTypePrivateKey).
Is there a way to convert it to .pem or .p12?
Assuming you mean "certificate" by .pem, no. If you mean PEM encoded, sure. It's either "BEGIN PRIVATE KEY" or "BEGIN ENCRYPTED PRIVATE KEY", depending.
It can also, technically, be converted into a PKCS#12. But Apple's PKCS#12 importer won't import (last I saw) private keys that it can't figure out what certificate they belong with (from the same PKCS#12).
This is just a private key, there's no certificate (thus no expiration). So certificate-based approaches don't make sense.
Does the server side can operate with .p8 the same way as .p12 or it should be additional tools added?
This depends entirely on the details of the protocol, which I don't know. If the protocol transported the certificate then different machinery is involved with the conversion. If it just transported a signature and the server looked up the public key for verification then nothing changed server side.

It's a text file! The .p8 extension signifies a simple text file containing public/private key. You can open it with any text editor (TextEdit, vim, Sublime Text) to see your key.

Related

What to do when Azure Key Vault rejects certificate and says: Unsupported key operation(s): "wrapKey", "unwrapKey"

I am trying to generate X509 certificates in C# code (using the X509Certificate2 class) and upload them to an Azure Key Vault.
I have found out that if my certificate contains the flag X509KeyUsageFlags.KeyEncipherment, the vault will reject the certificate with this error message:
Unsupported key operation(s): "wrapKey", "unwrapKey". Supported values are "sign", "verify".
Does anyone know what to do about this? Of course I can remove that flag from my generated certificates, but I want to understand why Azure rejects it. Is it possible at all to upload certificates to an Azure Key Vault when they contain this flag?
I ahae read this documentation page, but it did not tell me much: https://learn.microsoft.com/en-us/azure/key-vault/keys/about-keys-details
(This is a more specific follow-up to my earlier question here.)
• You are encountering this issue because the key along with this x509 .pem certificate is not in correct format and not combined with the certificate. That is, the certificate type that you are importing should not have its information contained in it in base64-encoded byte form. It should be in its raw form.
Thus, the error signifies that the certificate key you are trying to import is to be used to sign and verify the application content and the application using this certificate will hash the data locally using the certificate’s keys. Thus, the certificate key should not itself be in other unacceptable form. Also, the key generation algorithm may not be supported as stated from the error that you are encountering.
• Hence, if you are importing a certificate in PEM(whether that be X509 certificate) format, then "contentType" should be "application/x-pem-file" type. The value parameter will just be the raw text contents of your PEM file and need not to be in base64-encoded-byte, because PEM certificate is already in a text format, so base64-encoding is not required. Thus, the private key of the certificate should be in the same format as the certificate contents encryption algorithm. It need not be masked or converted in another format and it should be combined with the certificate itself.
Please refer to the links below for more information: -
https://learn.microsoft.com/en-us/azure/key-vault/certificates/certificate-scenarios#formats-of-import-we-support
https://learn.microsoft.com/en-us/answers/questions/258583/import-certificate-api-for-azure-key-vault.html

What is Apple's certificate?

I'm trying to understand what the certificate is. I'm talking about the .cer file.
In the description it sounds like it is a public key but if it is, than why do I need Certificate Signing Request (CSR) when creating it?
Everywhere I can find "what is a developer certificate for" and so on, but there is no information what the certificate — as an entity — is.
So my questions are:
What is .cer file? (Not .p12)
What is the difference between certificate and public key?
1) The .cer is an commonly used extension for certificates.
Certficates are digitaly signed and encoded documents. To my understanding certificates are documents which contain data (strings etc.) and are encoded. Simply put it is a container for sensitive data.
For details read: DER vs CRT vs CRM vs PEM
2) The public key simply put is a value (String for example). This value is stored in a certificate .cer file.
For better understanding this video might help: Private and public key
The difference is that a certificate can contain a public key but a public key cannot contain a certificate.
A certificate certify who you are, its a kind of identity card or passport or whatever. A public key is something used to secure something, somehow like a real key closes a safety box not to let everyone have look inside.
Then you may have the need to certify that a public key is the one it claims. A certificate is (normally) obtained from another trusted authority (like your passport is delivered by a legal entity). If not how would you trust a public key I'll give to you? It can be a hacked public key, but if you have a certificate that belongs to it, then (if you trust the authority) you'll know it's really mine and not a forged one.
You may read Public Key Certificate on Wikipedia for example.
.cer files are certificates in some well defined format.

iOS Security: Web server and File system

I have gone through apple developer videos on Security they have mentioned to use ssl https certificates and keychain to deal with security.
My iOS app will be giving access to sensitive paid files. so hackers should not get access to these files. I will be using in app purchase, so that user can buy these file.
1) My first question is: Should i host my files on apple server (Hosted Contents) , is the apple to client communication secure enough or should i implement my own server code with certificates and ssl authentication.
2) i want to know or get idea on how to encrypt files using private key on my desktop machine and then upload it on my server. When asked for by my iOS app pass the public key and encrypted file and save the public key in Keychain for further use. I want this feature so as to save the file on disk without anyone getting access to it by jailbreaking or other hack.
3) What should be used as public and private keys and what type of encryption to use. Currently i have come across AES looks good enough but is there a better way? Can certificates itself used to encrypt data or pass keys?
4) Which certificate authority to contact for most secure certificates.
Thanks in advance...
EDIT:
Main purpose to achieve is to download pdf and that pdf should not be accessible to user outside the app.
1) I have decided to use root certificates from CA and https to transfer content, to avoid MINM.
2) On app side i will generate public private key pair.
3) Save Private key in keychain.
4) Send Public key to server.
5) Server will encrypt pdf using MAIN-AES-Key.
6) MAIN-AES-Key will be encrypted using Public key sent by app.
7) Encrypted-pdf and Encrypted-MAIN-AES-Key will be sent to app.
8) Encrypted-pdf will saved to disk with secure write options just incase.
9) Encrypted-MAIN-AES-Key will be saved in keychain.
10) To decrypt pdf: Private key generated by app will be used to decrypt Encrypted MAIN-AES-Key and MAIN-AES-KEY will be used to decrypt pdf.
11) Finally will be trusting Apple-KeyChain to keep Private-Key secure.
The solution is unnecessarily complicated. The more complicated, the less secure due to more potential errors/over-sights.
Do use https with a CA signed certificate
To avoid MITM pin the certificate on the app side
There is no need to further encrypt the data being sent over https
Encrypt the file on the device and save:
Create an encryption from random bytes
Save the key in the Keychain
Create an iv from random bytes
Add the iv to the beginning of the encryption buffer
Encrypt the data with AES, CBC mode and PKS7 padding into the buffer following the iv
Save the data into a file the the app file area, possibly under the Documents or Library directory
Decrypt the file on the device and use:
Get the key from the Keychain
Read the encrypted data file
Get the iv from the beginning of the data
Decrypt the data starting just past the iv
Do not ignore the server
Use two factor authentication.
Properly hash with a salt any passwords
Use good user authentication
For the app data encryption consider using RNCryptor instead of writing the encryption portion yourself.

Is it possible to generate certificate signing request(.csr) using security framework in iOS?

I would like to make HTTPS request with a server require client-certificate authentication. I looked into this Creating a SecCertificateRef for NSURLConnection Authentication Challenge. It worked as expected.
However, it needs to prepare the p12 file which includes the private key. It would be secured as it needs a password to import the p12 file using SecPKCS12Import().
However, there could be other option. That is the iOS-client should make a certificate signing request(.CSR) and let a third party (the server) sign it.
For my search, I see that I can use SecKeyGeneratePair() for generating a key pair. But I don't see any API that generate a CSR.
Do I really need OpenSSL to achieve this?
Also, a bit off topic, once the iOS-client somehow receives the signed certificate. I can use SecCertificateCreateWithData() to retrieve an SecCertificateRef(). However, to fill in a NSURLCredential. I also need the SecIdentityRef which come from p12 file using SecPKCS12Import(). How can I retrieve a SecIdentityRef without SecPKCS12Import() but just a certificate file like crt or der?
There is no explicit support for CSR in Security Framework in iOS. However, it is not that difficult to build CSR 'manually' - it is just ASN.1 DER block of data that are available at iOS runtime.
Here is pseudo code of that:
Use SecKeyGeneratePair() from Security Framework to create fresh public/private key
Implement getPublicKeyBits method to retrieve NSData-form of fresh public key (see https://developer.apple.com/library/ios/samplecode/CryptoExercise/Introduction/Intro.html )
Implement getPrivateKey method to retrieve SecKeyRef from Keychain
Follow http://www.ietf.org/rfc/rfc2986.txt to construct ASN.1 DER of CSR in NSMutableData
Use CC_SHA1_* to create signature hash of Certification Request Info (part of CSR)
Use SecKeyRawSign and private key to sign CSR
This will create proper CSR (in form of NSData) that can be sent to CA for approval.
My implementation is available on GitHub: http://github.com/ateska/ios-csr .
To anyone who comes across this in the future, I encountered outfoxx's Shield library which makes it super easy to create CSRs via Swift.

Recover signing certificate without p12 password?

I've been handed an iOS app codebase, which I'd like to distribute via the existing Enterprise certificate used by the prior developer.
After importing the provided .mobileprovision file, I'm (not unsurprisingly) getting the "Valid signing identity not found" error. Specifically when building:
The identity '[name]' doesn't match any valid, non-expired certificate/private key pair in your keychains
I was given the original CertificateSigningRequest.certSigningRequest file, a .p12 file, and the .cer file. I was not given the password to the .p12 file.
Is it possible to rebuild what I need from the CertificateSigningRequest.certSigningRequest without the .p12 file's password? I can likely get the .p12 password, but not in a timely manner.
Thanks!
I recognize that you've solved your issue by getting the password for the .p12 file, but I thought I'd shine a little light on what lives in each of those files you mentioned for the benefit of anyone running across the question in the future.
To answer the main question in this question: Can I rebuild what I need from the CertificateSigningRequest.certSigningRequest file?
Regrettably the answer is a very solid 'No'. The root cause of this is the very heart of Public Key Infrastructure (PKI), a set of management technologies, people, and practices dealing with the creation, verification, use, and revocation of digital certificates. Central to PKI is the notion of a public-private key pair. The 'Public' key is the one you share widely, anyone may have a copy of it and anyone wishing to validate messages signed by a digital certificate will require access to this key. The 'Private' key is the linked key that only you (or more accurately, your machine) knows and uses when signing messages. It is this signature that is verified via use of the 'Public' key that is shared widely authenticating that the message is in fact authentic.
When we are constructing development or distribution certificates, we are inherently asking Keychain Access, openssl, or your preferred SSL toolchain to create a public-private key pair. The public key goes into the CertificateSigningRequest file along with the other 'Subject' fields like name and email address and we ship this file off to Apple. That file primarily tells Apple what Public Key they can use to validate your app signature -- it does not give them a copy of your Private Key after all, if others had your private key they'd be able to codesign as you effectively destroying the notion of accountability on the iOS platform (ex. This App's signature checks out as valid, but I still don't know if it was actually signed by a developer I trust...). At no point in time, is your Private Key transmitted to Apple or the Developer Portal; it resides quite happily in your Keychain until such a time as 1) The certificate expires, 2) you actively revoke the certificate from the Developer Portal, or 3) you accidentally (or intentionally) delete the keypair from Keychain.
So what lives in each of these files?
CertificateSigningRequest.certSigningRequest - This contains a copy of the Public Key from the Public-Private keypair you generated locally, plus some additional required subject information required by the Certificate Signing Request format. Apple disregards this additional information and uses the name and email address they have on file for your Developer Account when constructing your certificate.
.p12 - This is a PKCS#12 formatted file containing a copy of the Apple-issued Certificate (which itself contains the Public Key) and a copy of the linked Private Key. This data is encrypted to prevent unauthenticated access and thus requires a password to decrypt.
.cer - This is the Apple-issued Certificate that contains the Public key portion of the key pair. This certificate is used by Apple to validate that Apps you submit are not tampered with while in transit to the App Store review team:
You sign your app using the Private key that only you know and upload the signed binary to Apple.
Apple then validate the signature using the public key that you've already shared with them.
If the math works out, then the App hasn't been tampered with and you are good to go.
If the math doesn't work out, either the app was tampered with, or (much more likely) the certificate was revoked or regenerated and the app was signed with an old or incorrect key pair.
As you can see, the only places the Private Key resides is in the original developer's keychain as well as the encrypted .p12 file. Consistent with both your comment and flup's comment, you either have to get the password to that .p12 file or look into breaking through the encryption.
Regardless, good to hear that you were able to get the password from the original developer. Let me know if you have any followup questions.

Resources