What prevents CA private key from being calculated based on CA public key? - ssl

In RSA you basically have two primes for decryption and product for encryption. Normally you make decryption key private and and encryption public, however for CA signature verification the roles are reversed - CA encrypts the signature and browser decrypts it, so the decryption key is public. This means that the two primes are public, and once they are known everybody can multiply them together and get their dirty hands on the super-secret CA private key. What am I missing here?

Normally you make decryption key private and and encryption public, however for CA signature verification the roles are reversed - CA encrypts the signature and browser decrypts it, so the decryption key is public.
The signature is done on the server side by using the private key only known to the server. The signature is validated by the client using the public key. This means only the public key is public and the private key stays secret at the server.
This means that your assumption that both primes are public is wrong.

CA encrypts the signature and browser decrypts it, so the decryption key is public
No, the CA signs the message with the private key; and others can verify the message using the public key.
What am I missing here?
The confusion probably comes from the way that many people learn how signing works, specifically because they learn about RSA as "encryption" is m^e % n and "decryption" is m^d % n. Then you learn that "signing" is a proof-of-private-key, done by m^d % n and "verification" is done by doing m^e % n and comparing the expected result to the digest of the message. Conclusion: signing == decryption.
The reason you get taught that is because RSA is a hard algorithm to work out on paper (and even hard to write correctly for the computer) if you are using "sensible" payload sizes (that is, any size big enough to hold even an MD5 hash (128 bits), which would require a minimum key size of 216-bit, resulting in doing ModExp with 5.26e64 < d < 1.06e65)
For RSA encryption (PKCS#1 v1.5 padding) you take your original message bytes and prepend them with
0x00
0x02
(n.Length - m.Length - 3) random non-zero values (minimum 8 of these)
0x00
So encryption is actually (00 02 padding 00 m)^e % n; or more generically pad(m)^e % n (another encryption padding option, OAEP, works very differently). Decryption now reverses that, and becomes depad(m^d % n).
Signing, on the other hand, uses different padding:
Compute T = DER-Encode(SEQUENCE(hashAlgorithmIdentifier, hash(m)))
Construct
0x00
0x01
(n.Length - T.Length - 3) zero-valued padding bytes
0x00
T
Again, the more generic form is just pad(m)^d % n. (RSA signatures have a second padding mode, called PSS, which is quite different)
Now signature verification deviates. The formula is verify(m^e % n). The simplest, most correct, form of verify for PKCS#1 signature padding (RSASSA-PKCS1-v1_5) is:
Run the signing padding formula again.
Verify that all the bytes are the same as what was produced as the output of the public key operation.
PSS verification is very different. PSS padding a) adds randomness that PKCS#1-signature padding doesn't have, and b) has a verify formula that only reveals "correct" or "not correct" without revealing what the expected message hash should be.
So the private key was always (n, d) and the public key was always (n, e). And signing and decrypting aren't really the same thing (but they both involve "the private key operation"). (The private key can also be considered the triplet (p, q, e), or the quintuple (p, q, dp, dq, qInv), but let's keep things simple :))
For more information see RFC 8017, the most recent version of the RSA specification (which includes OAEP and PSS, as well as PKCS#1 encryption and PKCS#1 signature).

Normally you make decryption key private and and encryption public, however for CA signature verification the roles are reversed - CA encrypts the signature and browser decrypts it, so the decryption key is public.
No. The signature is signed with the private key and verified with the public key. There is no role reversal of the keys as far as privacy is concerned. If there was, the digital signature would be worthless, instead of legally binding.
This means that the two primes are public
No it doesn't.
What am I missing here?
Most of it.

CA works as a trusted authority to handle digital certificates. In RSA digital signature, you have the private key to sign and the public key to verify the signature. Your browsers have the public keys of all the major CAs.The browser uses this public key to verify the digital certificate of the web server signed by a trusted CA. So the private key is not public and you can't compromise it. You can do a simple google search to get a clear understanding of CA and digital certificates.

Related

How can I verify with mbedtls, that a cert validates a key?

Mbedtls can validate an x509 cert with its mbedtls_x509_crt_verify(...) function (link).
However, what I have:
A public/private key pair (saved in an mbedtls_pk_context).
A certificate I've got from a different source (thus, there is no guarantee that it does not contain any, possible intelligent modifications).
There is no problem with the validation of the certificate.
However, what if that certificate validates a different key? (What can be the result of a software problem and also a crack attempt.) Of course, such a key/cert pair will be unable for a tls handshake, but I don't think that I would need to build up a tcp connection for that.
This source (although it is for openssl scripting) makes likely, that certificate-key matching validation can happen with simply a modulus match.
There is also an mbedtls_pk_verify(...) function (ref), but it seems to me that it plays mostly with signatures. But I have no signatures, I have a cert (got in a pem format), and my key (I have also that in a pem format). Processing them into internal mbedtls data structures (mbedtls_x509_crt and mbedtls_pk_context) is not a problem, but how could I verify that they match?
As this security.SE answer says, for the validation is it enough, if the pubkey in the certificate and in the private key file are the same. It is because it is the only shared information common in them.
Thus, we need to dig out the public key from the mbedtls_pk_content and from the mbedtls_x509_cert and compare them.
The mbedtls has no general API call for this task, but it can be done by algorithm-specific solutions. The steps are the following. Assume that we have
mbedtls_x509_cert crt;
mbedtls_pk_context pk;
Where crt has the certificate and pk is our public-private key pair.
We get the keypair from both. In the case of elliptic curve ciphers, it is being done by the mbedtls_pk_ec(...) macro. In the case of rsa, mbedtls_rsa_context(...) is needed:
mbedtls_ecp_keypair* crt_pair = mbedtls_pk_ec(crt->pk);
mbedtls_ecp_keypair* pk_pair = mbedtls_pk_ec(*pk);
Note, although crt_pair is now a keypair, only its public part will be non-zero, because the certificate has obviously no private key part. mbedtls_pk_ec(...) looks to be some macro-like thing to me, because it doesn't use a pointer to the structs, instead it uses directly a struct.
Then, we compare the public keys in the keypairs:
mbedtls_mpi *pk_pub_X = &pk_pair->Q.X;
mbedtls_mpi *pk_pub_Y = &pk_pair->Q.Y;
mbedtls_mpi *crt_pub_X = &crt_pair->Q.X;
mbedtls_mpi *crt_pub_Y = &crt_pair->Q.Y;
In the case of other algorithms (RSA), these parts might differ, however we always need to have a set of big numbers (mbedtls_mpi), and compare these big numbers.
Then, we use the mbedtls big number functionality to compare them:
bool does_it_differ = mbedtls_mpi_cmp_mpi(pk_pub_X, crt_pub_X) || mbedtls_mpi_cmp_mpi(pk_pub_Y, crt_pub_Y);
Note: verifying the cert match is not enough to verify the cert validity, it is only required for that. The verification of the certificate can be done with the already much more pleasant and simpler mbedtls_x509_crt_verify(...) function.
I know this is an older question, but perhaps mbedtls_pk_check_pair is what you are looking for. Pass it your private/public key pair and the certificates public key.
/**
* \brief Check if a public-private pair of keys matches.
*
* \param pub Context holding a public key.
* \param prv Context holding a private (and public) key.
*
* \return \c 0 on success (keys were checked and match each other).
* \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not
* be checked - in that case they may or may not match.
* \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid.
* \return Another non-zero value if the keys do not match.
*/
int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv );

Where Bitcoin using ECDSA and ECDH

1.var hash = crypto.randomBytes(32);
2.var publickey = ecdh.setPrivateKey(hash,'hex').getPublicKey('hex');
then sha256 => ripemd160 => encode... => address
I know how the bitcoin address generated,but seems it just using ECDH to generate bitcoin address,but I saw lots of talk says it using ECDSA,I want to know where bitcoin using ECDSA and how bitcoin using cryptography to verify transaction and which crypto function using for signing transaction.
Thanks.
Bitcoin doesn't use ECDSA for its address generation, save from the fact that you can use the public key of the ECDSA to generate a Bitcoin address. Where the Elliptic curve is really used is in signing the transaction.
First you create a raw transaction with all the correct fields in, including the ScriptPubKey and then convert that to list of bytes. You then take the SHA256 of the transaction bytes and then SHA256 the result of the SHA256. This is the message digest and this is what you need to sign with the ECDSA private key to generate the SigScript. The SigScript however contains more than just the signed digest. First comes a digest length + 1 for the SIGHASH_CODE, then comes the signature itself, followed by sig hash code, then a length for the public key and finally the public key itself. Once you've concatenated all of these, that's your SigScript that needs to be inserted into the transaction. Obviously the entire SigScript is prefixed with a size, just like the SigPubKey. Lastly insert the size and the result and now you have a signed transaction you can broadcast.

CryptoAPI wrapped keys

With CryptoAPI, is there a way to decrypt (using CryptDecrypt) a key written into a SYMMETRICWRAPKEYBLOB?
In my c++ program, i wrap a symmetric key k1 with another symmetric key k2 into a symmetric key blob. I have a third key, k3, equal to k2 but with a different handle. My goal is to decrypt the blob with this key. I have already did it using a SIMPLEBLOB and a public key.
Thanks in advance for your attention.
Documentation here
As the documentation you link to says, the format used for SYMMETRICWRAPKEYBLOB follows RFC 3217. It is a weird format in which the data is encrypted, then reversed (last byte becomes first, and so on), and then encrypted again. Both encryptions use CBC. If you want to do it by hand, instead of using CryptImportKey(), then you will have to follow RFC 3217, with two calls to CryptDecrypt(), and your code will also have to do the byte reversal and the rest of the packaging.
Alternatively, import the key blob with CryptImportKey(), then export it again by encrypting with an asymmetric (RSA) key of your own, which you can then decrypt. At some point, Microsoft themselves were documenting that, in order to export a symmetric key "as is", the best way was to call CryptExportKey() with a handcrafted RSA public key with a public exponent equal to 1, i.e. not really a correct RSA key -- with such a public exponent, RSA encryption is mostly a no-operation.

Is the result of a RSA encryption guaranteed to be random

I use RSACryptoServiceProvider to encrypt some small blocks of data. For the solution I'm working on, it's important that if the same piece of source data is encrypted twice with the same public key, the result (the encrypted block of data) is not the same.
I have checked this with an example and it worked like I hoped. My question is now, if this behaviour is by design and guaranteed or if I have to add some random part to the source data for guaranteeing that data blocks with the same data can not be matched anymore after encryption.
Here is the example:
byte[] data=new byte[]{1,7,8,3,4,5};
RSACryptoServiceProvider encrypter = cert.PublicKey.Key as RSACryptoServiceProvider;
byte[] encryptedData = encrypter.Encrypt(data,true);
// encryptedData has always other values in, although the source data is always
// 1,7,8,3,4,5 and the certificate is always the same (loaded from disk)
The concrete question is for .net but maybe the answer can be given in general for all RSA-implementations if it is by design?
The text-book RSA encryption algorithm is deterministic:
ciphertext = plaintext ^ encryption-exponent mod modulus
(Here ^ is integer exponentiation, mod the remainder operation.)
But as you remarked, this does not provide a good security guarantee, as an attacker which can guess the plaintext can simply verify this guess by encrypting it himself and comparing the results.
For this reason, the official RSA specifications (and also all implementations used in practice) include some (partly random) padding, so we don't actually encrypt plaintext, but pad(plaintext):
ciphertext = pad(plaintext) ^ encryption-exponent mod modulus
Decryption:
plaintext = unpad( ciphertext ^ decryption-exponent mod modulus )
Only with this padding RSA is actually a secure encryption scheme.
A similar padding is also used for RSA signatures, to avoid easy forging of signatures.

Certificate structure

Most of signed certificate footprints are 20 byte long (field "footprint" in Windows certificate manager).
How can this be a value signed by an issuance (certification) authority? Concretly, the signature of the certificate should be the hashed value of the certificate fields signed by a private key and thus have at least the RSA modulus length (in the case of a RSA signature) of the issuer private key and thus... be at least 512 bits (64 byte) long.
There is something I must be missing... If this footprint is only a hash, then it cannot be a signed certificate. Where is the certificate signature in fact ? it is not possible to check that the certificate is valid from a simple Hash.
Regards,
Apple92
Do you mean "fingerprint"? A fingerprint is only a hash and is only used as a convenience to lookup a certificate for comparison purposes. It is not part of the certificate proper, it is generated from the certificate by the certificate manager. The certificate signature is inside the certificate.
The certificate itself is composed of the identifying information and public key in a structure called a TBSCertificate (TBS is short for To Be Signed), plus the signature algorithm and the signature itself. See RFC5280 for all the gory details.
Fingerprint, which you can see via the Certificate Manager in Windows, is not a part of the certificate. It is dynamically generated by the Certificate Manager in favor of the convenience of identifying many certificates it manages.
A certificate consists of three parts. (Details are in https://www.rfc-editor.org/rfc/rfc5280#section-4.1)
tbsCertificate: This contains the names of the subject and issuer, a public key associated with the subject, a validity period, etc. This tbsCertificate(a.k.a certificate to be signed) is what an issuer(CA) reviews and signs for.
signatureAlgorithm: The identifier for the cryptographic algorithm used by the issuer(CA) to sign the tbsCertificate above. Algorithm varies. One of the most common algorithms is to hash the tbsCertificate (of DER format) to produce a digest, which is then encoded by the issuer(CA)'s private key. The result is stored in the next field, signatureValue.
signatureValue: This field is populated with the resulting value that is produced by the issuer(CA) using the signatureAlgorithm above.
The behavior of composing a certificate structure above by an issuer(CA) is called signing.