How does the signature in a digital certificate come from? - encryption

According to here:
A digital certificate contains:
Serial Number: Used to uniquely identify the certificate.
Subject: The person, or entity identified.
Signature Algorithm: The algorithm used to create the signature.
Signature: The actual signature to verify that it came from the
issuer.
Issuer: The entity that verified the information and issued the
certificate.
Valid-From: The date the certificate is first valid from.
Valid-To: The expiration date.
Key-Usage: Purpose of the public key (e.g. encipherment, signature,
certificate signing...).
Public Key: The public key.
Thumbprint Algorithm: The algorithm used to hash the public key
certificate.
Thumbprint (also known as fingerprint): The hash itself, used as an
abbreviated form of the public key certificate.
My question is, how does the signature come from? I think it is used to ensure the digital certificate is issued by a trusted issuer. So the issuer use its private key to sign on something to produce the signature, then the verifier of the certificate must have the corresponding public key of the issuer to decipher the signature and verify that this something is genuine.
If I am correct, this something must be stored in the certificate as well for the verifier to compare the deciphered signature to. So what's this something? Could it be the thumbprint (hash) of the public key?

This something is most of the certificate itself. The receiver can calculate the hash over the TBSCertificate (the part of the certificate To Be Signed) itself using the algorithm in the certificate. The receiver can then verify that it is the same as the hash calculated by the signer (the issuer of the certificate). If the signature is verified and the signer is trusted, then the certificate is verified.
There are more tests to be performed such as validating that the certificate has not been revoked or over it's date of expiry before it can be fully trusted.
A digital certificate consists of:
certificate information
signature algorithm
signature value
See the RFC 5280 for more info on the exact structure of the certificate.

Related

RSA public/private keys questions

I'm a newbie with encryption but I have a few questions. I know the subject is complicated, but I'm not asking specifically for the standard but what could work, that is to say, what should be secure, even if less than real RSA methods, even if it is not the standard but should be securized. It's questions about asymmetric encryption more generally.
1) Which private key is used to sign a Certificate ? Is it the private key related to the public key of the organization, or the private key of the autority. I think it's the first one because in Java, when I try to sign with a private key that is not the pair of the public key in the certificate, it fails (Edit. I know it may depend of the content of the "Certificate", and that a signature just sign a chunk of bytes).
If the private key of the organization is used to sign a Certificate: it means that the authority can't sign the certificate (it doesn't has the private key of the organization): does that mean that the signature is provided by the organization ?
2) It's related to question. 1 but do authority need a private key to generate certificate ? Like 2-pass signature, use the two keys to verify the signature. If yes, for which purpose specifically ?
Also if the autority doesn't need to have a private key, is it sufficient, for checking if a certificate is valid, that the certificate is right AND the authority contains the given public key in the database (or at maximum check byte by byte if the certificate in the database is the same that the one-to-check), on the assumption of the private key can not be deduced fro mthe public key ?
3) I'm confused with public/private and encryption/decryption relation. What I've seen and learn is that private encryption key is used to sign and private decryption key is used to securize communications, also we can say that encryption/decryption is just a term of langage and it has no other reality than conversion to a direction or the other. BUT in Java to sign a document with the class Signature you provide a private key to generate the signature (if i'm correct). On the other hand you use it to decrypt communications, right ? So you use it for encryption and decryption. Is it ok. to do so or do we need 2 pairs of keys to do securized communication, one for certificates and one for communications ?
4) Off-topic but I think the RSA keys are asymmetric but provide the same mathematical properties and also have a sort of symmetry, so we can encode with decryption key and reciprocally.
Is this example correct, just for curiosity:
to the left: encrypt with private key
to the right: encrypt with public key
... <-> messageP2 <-> messageP1 <-> message <-> messageR1 <-> message R2 <-> message R3 <-> ...
Thanks
the whole point of certificates is trust in a PKI (public key infrastructure)
a key in a PKI is allways a key pair. the private part is always kept secret by the owning party
there are way too many parties that everybody knows the public key of everybody else
everybody knows the public key of the CA (or a known CA has to sign the key of a sub-CA, if you want multiple layers of CAs)
everybody gets their public key embedded into a certificate signed by a CA
if you now want to communicate with someone, you ask for their certificate ... since you don't know them yet (or to be precise, you don't know their key yet) you can't be sure that you are communicating with the intended party
they send over their certificate...
now you can check the chain of trust:
their certificate is signed by someone ... is that someone trustworthy AND is the signature valid?
is that someone trustworthy? a quite simple question: is that someone a trusted CA that may sign certificates for the intended party? in other words: can we find the siging CAs certificate in our list of trusted CAs, or did another trusted CA sign their cert as a CA cert?
is the signature valid? can be tested if the signing CAs pub key is known
now what if we know this CA and trust it? ... everything is ok... but what if we don't know that CA? usually our communication partner can provide the certificate of that CA (since certificates are public, in other words, not secret)
now we can repeat ... is the presented CA cert signed by someone trustworthy and is the signature valid?
the whole point of this is: it's not required to have a huge database with all the public keys, and the communicating parties are able to verify identities on their own as long as they can verify the certs
so with this in mind ...
1) the CAs private key is used to sign a cert. The signature on a cert is equal to the statement "the signer can be held accountable for the validity of all the values in the cert"
2) the CA signs the certificate ... signing here is an operation that requires a key... just having the cert in a database at the CA does not suffice ... take into account that the identity of the certificate holder needs to be checked while there is no way of communicating with the CA
3) to lighten that confusion
sign / decrypt ... private key
verify / encrypt ... public key
usually cryptosystems for signatures and encryption are different ...
RSA is the unicorn here, it can be used for both
the idea behind a certificate is that you can embed public keys, and bind them to an identity in a way that a common trusted CA is enough for two otherwise unknown parties to safely exchange their keys
4)
from the math point of view ... yes ...
the RSA operation is X^e mod N = C ... C^d mod N = X
with X = plaintext ... C = ciphertext ... N,e,d rsa-parameters
the principle behind RSA is that e*d mod phi(N) = 1
therefore
(X^e)^e = X^(e*e)
(X^(e*e))^d = X^(e*e*d) = X^(e*1) = X^e
(X^e)^d = X^(e*d) = X^1 = X
The purpose of have a certificate issued by an authority is that the authority is certifying that the information in the key is accurate. In order for that certification to be verified, the certificate must be signed using a private key that is only known to the certifying authority.

How to generate a certificate with DH parameters

I need to support Diffie Hellman encryption, now in order to test this i need to create a certificate with DH key parameters eg. key-length - 2048 etc.
Now as i understand DH doesn't work with self-signed certificates, so basically i need to create a certificate issued by some trusted third party containing DH key parameters.
I searched a lot but can't seem to find proper direction, no where can i find a way to create a cert with DH parameters.
Can someone point me in right direction?? Thanks in advance!!
I need to support Diffie Hellman encryption
DH is key exchange (or key agreement) protocol, not encryption. DH is used to securely generate a common key between two parties, other algorithms are used for encryption itself.
I need to create a certificate with DH key parameters eg. key-length - 2048 etc
There is nothing like DH parameters in a certificate.
DH is only one of ways how a public key can be used. You may generate a DH public key with specified length (e.g. 2048 bit) and execute the DH exchange, but it has nothing to do with certificate parameters. (didn't you mean to generate a keypair, not a certificate?).
Indeed the DH key exchange needs other parameters (p, g), but the parameters are part of the protocol, not the certificate. In TLS even the DH parameters can be random and authenticated by the certificate's public key - it is called Ephemeral Diffie-Hellman key exchange.
You could generate DH parameters (p, g) separately:
openssl dhparam -out dhparams.pem 4096
Can someone point me in right direction??
Now I assume you want to establish an encrypted channel (TLS) using DH. The easiest way would be to specify allowed parameters for SSL for the library. This is an example httpd configuration, where you can enforce DH key exchange. Every reasonable SSL framework or server has option to set the parameters.
If you want to do the DH key exchange yourself (not as part of TLS), I'd advice to use an out-of-box mature library for your programming language.
Yes, it seems true that OpenSSL will not create a certificate for DH keys. You'll get an error like: operation not supported for this keytype. The reason someone would want to do this is that they want to store the DH public key in a keystore; which seems like a reasonable place to store them. In my case, I want my client application to be deployed with the server's public DH key. The problem is that keystores don't let you store public keys in them. They do however, let you store certificates in them. Hence the need for creating a certificate that contains a DH public key. Since you can't do this using OpenSSL, you'll have to do it in code. Here's the code that I use to create a certificate. If you pass in a DH public key, you'll be able to add this certificate to a keystore:
public X509Certificate createCert (PublicKey publicKey, PrivateKey caKey, X509Certificate caCert , String subject) throws Exception {
Date now = new Date();
Date exp = new Date(now.getTime()+2555*86400*1000); // 2555 days validity
BigInteger.valueOf(now.getTime());
ContentSigner signer = new JcaContentSignerBuilder("SHA256with"+caKey.getAlgorithm()).build(caKey);
SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(publicKey.getEncoded());
byte[] enc = new X509v3CertificateBuilder(
/*issuer*/ new X500Name(caCert.getIssuerX500Principal().getName()),
/*serial*/BigInteger.valueOf(now.getTime()),
/*validity*/now, exp,
/*subject*/new X500Name (subject),
/*spki*/subPubKeyInfo).build(signer).getEncoded();
X509Certificate cert = (X509Certificate)CertificateFactory.getInstance ("X.509") .generateCertificate(new ByteArrayInputStream(enc));
return cert;
}
The code uses several BouncyCastle classes. Besides passing in the DH public key, you have to pass in the CA private key and the CA certificate and a String that contains the subject for the certificate that you generate. Hope that helps for those wanting to store a DH public key in a keystore.

Is it possible to have multiple keys in oiosaml keystore?

I am working on OIOSAML with ADFS 2.0. I need the IdP response to be signed as well as encrypted. Below is my understanding on how signing and encryption of SAML request and response works:
SP signs the request using its own certificate key (Key-1)
IdP verifies the request using SP's public key (Key-1)
IdP signs the response using its own certificate key (Key-2)
IdP encrypts the response assertion using certificate key provided by SP (Key-3)
SP verifies response using IdP's public key (Key-2)
SP decrypts the response assertion using its own private key (Key-3)
If I keep Key-1 and Key-3 same, everything works. As my keystore in OIOSAML has only one key.
But now I want to use separate keys for request signing and response encryption. It fails here.
Does OIOSAML support multiple keys in keystore?
If yes then how does it distinguish between signing and encryption keys?
This feature is available from OIOSAML release 3.

Javascript Signing a message using an Eth address as public key

As far as I understand, on Ethereum every wallet has a private and a public key.
The public key is the address. What I want to achieve is to SIGN a "string" with a public address, so that only that address (with the private key) can "read" the message.
I'm struggling in finding the best library to do this: I've seen openpgp and JEncrypt but both requires to have "public / private" keys specified in some particular format.
Is there any SDK that can help? With web3 is possible only to sign with private key..
The term "sign" in public-key cryptography has a very specific meaning: it generally means the generation of a digital signature to verify the content and sender of a given message.
It sounds like what you're describing when you say "SIGN" is that you want to encrypt a message with the ETH address / public key, and decrypt the message with the wallet private key.
In public key cryptography, you encrypt with the public key and decrypt with the private key.
I'm struggling in finding the best library to do this: i've seen openpgp and JEncrypt but both requires to have "public / private" keys specified in some particular format.
Public and private keys will need to be in the proper format for any pgp implementation, and this is likely the problem with ETH addresses, because the ETH address is derived from the underlying key pair. This blog post contains a detailed explanation of the relationship between ETH addresses and key pairs.

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.

Resources