Reading RSA private key from X509-certificate results in different output on Windows Server 2016 vs. Windows Server 2019 - cryptography

here is my issue:
In C#/.NET-4.8, I use a P12 certificate with RSA private key on 2 servers.
One server runs Windows Server 2016, the other Windows Server 2019.
When I compare the RSA private keys of the same certificate on both servers, the output is not the same.
The “private exponent” (found in the “D” property) is not the same.
Does anyone know why this happens?
Extra info:
The code keeps outputting the same key (per system), every time it runs (which of course is good).
The code outputs the same private key on Windows 10, Windows 11, and Windows Server 2019 but on Windows Server 2016 it is different.
The code to read out the certificates key is:
using (var rsaPrivateKey = _certificate.GetRSAPrivateKey())
{
var parameters = rsaPrivateKey.ExportParameters(true);
privateExponent = BitConverter.ToString(parameters.D); // privateExponent (parameters.D) is the components which is not the same on each system.
privateKeyXml = rsaPrivateKey.ToXmlString(true); // In privateKeyXml, only the privateExponent changes.
}
Thanks in advance for any help!

Two pieces of background knowledge that you need for the answer to make sense:
RSA private keys are encoded redundantly. (n, e, d, p, q, dp, dq, qInv) could really just be (n, e, p, q).
Back in the day computing d/dp/dq/qInv was "hard", and so the file format was "save yourself the effort of recomputing this" -- though that left a possibility that the values aren't consistent.
There are two different ways to compute d ("lambda" and "phi"), both values work.
Windows CNG, from Vista until ~2019, discarded the d/dp/dq/qInv values when importing a key and recomputed them using (I believe) the lambda approach.
For some reason, in ~2019, they either changed to forcing the computation with phi, or they started saving the import values and faithfully reporting them on export.
Either way, it doesn't really matter, as the true key is just (n, e, p, q). As long as those 4 don't change, you have the same key.

Related

What is actually in known_hosts? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 7 years ago.
Improve this question
I did not have an .ssh directory until I ran
ssh user#foo.com
This created a .ssh directory with one file known_hosts.
It had some text like this in it.
foo.com,107.180.00.00 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAuJfqSnraBz//Ux4j/hZpLv2eYUxNUgCk+9ClqoSgfcu4vXbWtUGSjo75UVQf+uguOeBnRLppJJ3mt0R5c/PPcawUGWfffk33t+biYcqra9xUcyfiGtO/Icko2L1J0EYTXM/8x8VK6UYFMfad2gltnZRa8Am50oHTXot1Df0RljUBxvh/UhmTJUrODpyrl2xY1OMWjM+S6uYCMNeSQGEpNfsWiCIStRnctMZSxiYJOLTSC4F2GF7B8pYFBn5rSwVHp17WCdO+4BZfwvH3HSSH8IWoyFhki+NlG912SEBJXcryvc0JPfAB9DTB4mRImjgrRT8vz5QeaCDrh8k4/A+U1fff
I thought this might have been a public or private key pulled of my server some how, but it was not.
What is this, and what is it used for?
I'm just trying to learn more about ssh and how it works. For example in this case I did not setup the private key on the local machine so it prompted for a password as expected.
Research
It's suppose to be a public key for the server according to
https://security.stackexchange.com/questions/20706/what-is-the-difference-between-authorized-key-and-known-host-file-for-ssh
This file is, effectively, your personal Certificate Authority. It is the list of all SSH server host public keys that you have determined are accurate. Each entry in known_hosts is one big line with three or more whitespace separated fields as follows:
a. One or more server names or IP Addresses, joined together by commas.
foo.com,107.180.00.00
b. The type of key.
ssh-rsa
c. The public key data itself encoded to stay within the ASCII range.
AAAAB3NzaC1yc2EAAAABIwAAAQEAuJfqSnraBz//Ux4j/hZpLv2eYUxNUgCk+9ClqoSgfcu4vXbWtUGSjo75UVQf+uguOeBnRLppJJ3mt0R5c/PPcawUGWfffk33t+biYcqra9xUcyfiGtO/Icko2L1J0EYTXM/8x8VK6UYFMfad2gltnZRa8Am50oHTXot1Df0RljUBxvh/UhmTJUrODpyrl2xY1OMWjM+S6uYCMNeSQGEpNfsWiCIStRnctMZSxiYJOLTSC4F2GF7B8pYFBn5rSwVHp17WCdO+4BZfwvH3HSSH8IWoyFhki+NlG912SEBJXcryvc0JPfAB9DTB4mRImjgrRT8vz5QeaCDrh8k4/A+U1fff
d. Any optional comment data.
Also!!
This thread might be of use for you:
https://security.stackexchange.com/a/20710
To add to the answer above and your comment,
There are four building blocks for ssh session
Encryption( symmetric keys derived after key exhange per session)
Data integrity (MAC using eg SHA,HMAC )
Key exchange methods
Public key methods or host key methods
the SSH algorithm negotiation involves a key exchange state machine
which begins when the SSH_MSG_KEXINIT message along with algorithms list is sent.
The key exchange method or simply kex specifies session keys for encryption and host authentication host public keys(ssh-rsa, ssh-dss ..) that are sent to the client. The step below are the basic steps that take place for kex using Diffie hellman key exchange algorithm
quoting the RFC https://www.rfc-editor.org/rfc/rfc4253
The following steps are used to exchange a key. In this, C is the
client; S is the server; p is a large safe prime; g is a generator
for a subgroup of GF(p); q is the order of the subgroup; V_S is S's
identification string; V_C is C's identification string; K_S is S's
public host key; I_C is C's SSH_MSG_KEXINIT message and I_S is S's
SSH_MSG_KEXINIT message that have been exchanged before this part
begins.
C generates a random number x (1 < x < q) and computes
e = g^x mod p. C sends e to S.
S generates a random number y (0 < y < q) and computes
f = g^y mod p. S receives e. It computes K = e^y mod p,
H = hash(V_C || V_S || I_C || I_S || K_S || e || f || K)
(these elements are encoded according to their types; see below),
and signature s on H with its private host key. S sends
(K_S || f || s) to C. The signing operation may involve a
second hashing operation.
C verifies that K_S really is the host key for S (e.g., using
certificates or a local database). C is also allowed to accept
the key without verification; however, doing so will render the
protocol insecure against active attacks (but may be desirable for
practical reasons in the short term in many environments). C then
computes K = f^x mod p, H = hash(V_C || V_S || I_C || I_S || K_S
|| e || f || K), and verifies the signature s on H.
the local database mentioned in step three in certain systems could be the .ssh/known_hosts file.
So to answer your question the public key is sent to the client by the host during the key-exchange.
The following public key and/or certificate formats are currently defined:
ssh-dss REQUIRED sign Raw DSS Key
ssh-rsa RECOMMENDED sign Raw RSA Key
pgp-sign-rsa OPTIONAL sign OpenPGP certificates (RSA key)
pgp-sign-dss OPTIONAL sign OpenPGP certificates (DSS key)

What makes the trapdoor function in elliptic curve cryptography hard to reverse?

I've been reading this article on elliptic-curve crypto and how it works:
http://arstechnica.com/security/2013/10/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/
In the article, they state:
It turns out that if you have two points [on an elliptic curve], an initial point "dotted" with itself n times to arrive at a final point [on the curve], finding out n when you only know the final point and the first point is hard.
It goes on to state that the only way to find out n (if you only have the first and final points, and you know the curve eqn), is to repeatedly dot the initial point until you finally have the matching final point.
I think I understand all this - but what confuses me is - if n is the private key, and the final point corresponds to the public key (which I think is the case), then doesn't it take the exact same amount of work to compute the public key from the private, as it does the private from the public (both just have to recursively dot a point on the curve)? am I misunderstanding something about what the article is saying?
The one-way attribute of ECC and RSA is due to the Chinese Reminder Theoreom (CRT). A series of arithmetic divisions where only the remainder is kept (aka Modulo operation %), which results in information loss in the output. As a result, the person with the keys takes one direct path to generate the output - and any would-be attacker has to exhaust a massive number of possible paths in order to determine what key was used to create the output. If the simple division was used instead of a modulo - then key data would be present in the output and it couldn't be used for cryptography.
If you lived in a world where you had a powerful enough computer to exhaust all possibilities - then the CRT wouldn't be useful as a cryptographic primitive. The computers we have now a fairly powerful - so we balance the power of our modern machines with a keysize that introduces enough range of possibilities so that they cannot be exhausted in a timeframe that matters.
The CRT is a subset of the P vs NP problem set - so perhaps proving P=NP may lead to a way of undermining the oneway aspect of asymmetric cryptography. We know that there is a way to factor CRT using a quantum computer running Shor's Algorithm. Shor's Algorithm has proven that we can defeat the so-called "trapdoor", or one-way attributes of CRT, it is still however an expensive attack to conduct.
The following lecture is my favorite description of the CRT. It shows that there are many possible solutions for one direction forcing an attacker to exhaust them all and only one solution for the other:
https://www.youtube.com/watch?v=ru7mWZJlRQg
EDIT: I previously stated that n is not the private key. In your example, n is either server or client private key.
How it works is that there is a starting point known to anybody.
You select random integer k and do the "dotting operation" k-times. Then you send this new point to the server. (k is your private key)
Server does the same with the starting point, but q-times and sends it to you. (q is server's private key)
You take the point you got from server and "dot" it k-times. The final point would be the starting point "dotted" k*q-times.
Server does the same with point it got from you. And again its final point would be the starting point "dotted" q*k-times.
That means the final point (= the starting point "dotted" k*q-times) is the shared secret since all what any attacker would know is the starting point, the starting point dotted k-times and the starting point dotted q-times. And given only those data, it's practically impossible to find the final point as a product of k*q unless any of those known.
EDIT: No, it doesn't take the same time to compute k from G = kP given known values of G (sent point) and P (starting point). More in comment section and:
For rising to power, see Exponentiation by squaring.
For ECC point multiplication, see point multiplication.

Is it common to negotiate which DH group is used during a Diffie-Hellman key exchange?

When I read descriptions about how DH key exchange works, there's no mention of how the key-exchangers came to an agreement on which "group" (the p and g parameters) should be used to compute the public and private values. Looking at RFC 5114, it seems like there are quite a few choices.
I'd like to know if this negotiation is typically done during the exchange itself, and if not, if there's a description somewhere regarding how the algorithm would be different if it included that step.
Thanks for reading.
The p and g values are safe to pass unencrypted. If client/server is on a network, either the client or server generates the p/g values and passes them via network sockets. As long as the secret number for each client/server is kept a secret (duh..) the Diffie-Hellman exchange can said to be safe as a attacker would have to compute g^(ab) mod p = g^(ba) mod p (which leads to a infinite amount of solutions that is infeasible to compute given that the p value is big enough).
Essentially the most basic D-H exchange goes as follows:
Party A generates p, g, a values. Where g is the base/generator, p is the prime modulo, a is the secret power.
Party B (concurrently) generates secret value b.
Party A computes g^a mod p (we call this value thereafter A)
Party A and sends p, g and A across the transmission medium.
Party B receives p, g, A.
Party B computes g^b mod p (we call this value thereafter B).
Party B sends B across the transmission medium.
Party A receives B.
Party A computes B^a mod p and obtains the shared secret.
Party B (concurrently) computes A^b mod p and obtains the shared secret.
Note: if the p value is too small, it may be computational cheaper to just iterate through 0 to p - 1 but this all depends on what you do after you generate the common secret.

Xcode Openssl RSA decryption function needed

I am reading an encrypted string from an application in xcode and I have to write a function that uses RSA decryption to decode and display the message.
I am completely lost on where to begin with this.
I have Openssl complied in xcode and I am using the openssl/rsa.h file.
I am trying to use the function:
RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);
But then I'd read somewhere on the Openssl main site that the function just returns a number and not the actual string. I also have no idea what paramenters to pass through.
The only reference I have found is the openssl/rsa.h file and looking at the functions it contains.
I've tried doing some research the past couple hours but I have no found any answers.
I was wondering if there is a simple function that I can pass my encrypted string and my private key (using a file or hardcoded) and it can return the decrypted string?
If not is there a guide on how to use Openssl with Objective C programming?
Please let me know if you need more information on the issue.
Thank you in advance.
You may want to look Apple's example which uses security transforms (this avoids openssl) in their Security Overview.
With a bit of luck you can do things with apple transforms and go with that programme.
If not - or if for some reason you really want to use openssl; then the openssl source contains the example file openssl-0.9.8t/apps/rsa.c which pretty much allows for selective cut-and-paste to make things work.
Doing man RSA_private_decrypt from the command line will show you the manual page (or from within Xcode to the man page). Or see http://www.openssl.org/docs/crypto/RSA_public_encrypt.html.
Example use for the above:
unsigned char in[] = { 1, 2, ... byte array to decrypt };
// size of that in byte array
int inlen = sizeof(in);
// output buffer size depends on the key type.
char * out = malloc(RSA_size(rsa));
int e = RSA_private_decrypt(inlen, in, out, rsa, RSA_PKCS1_PADDING);
where padding is one of the values from the man-page.
The value of rsa is a bit more complex to initialise as this is where you set up your keys and what not. Check the above rsa.c file for examples of various ways of filling it - it normally boils down to something like:
EVP_PKEY *pkey = load_key( ... , password,... );
rsa = EVP_PKEY_get1_RSA(pkey);
where load_key is borrowed from the app examples of openssl.

Why RSA Decryption process takes longer time than the Encryption process?

I have some idea that it is due to some complex calculation, but i want to know about what exactly happens which takes long time than the corresponding encryption process. Any link to webpage or paper would be of great help.
Thanks
Thanks for the answers, One more Doubt, What about the Signing and verification? Will this time difference be there for Signing and verification also? Ex. Signing requires more time than Verification?
Let's call n, d and e the RSA modulus, private exponent and public exponent, respectively. The RSA decryption speed is proportional to (log d)(log n)2 (i.e. quadratic in the length of the modulus, and linear in the length of the private exponent). Similarly, the RSA encryption speed is proportional to (log e)(log n)2. The private key holder also knows the factorization of n, which can be used to speed up private key operation by a factor of about 4 (with the Chinese Remainder Theorem). For details on the involved algorithms, see the Handbook of Applied Cryptography, especially chapter 14 ("Efficient Implementation").
For proper security, the private exponent (d) must be big; it has been shown that if it is smaller than 29% of the length of the modulus (n) then the private key can be reconstructed. We do not know what is the minimum length to avoid such weaknesses, so in practice d will have about the same length than n. This means that decryption will be about cubic in the length of n.
The same provisions do not apply to the public exponent (e), which can be as small as wished for, as long as it complies with the RSA rules (e must be relatively prime to r-1 for all prime factors r of n). So it is customary that a very small e is chosen. It is so customary that there are widely deployed implementations that cannot handle big public exponents. For instance, the RSA implementation in Windows' CryptoAPI (the one used e.g. by Internet Explorer when connected to a HTTPS site with a RSA server certificate) cannot process a RSA public key if e does not fit in 32 bits. e=3 is the best possible, but e=65537 is traditional (it is an historical kind of blunder, because a very small exponent can induce a perceived weakness if RSA is used without its proper and standard padding, something which should never be done anyway). 65537 is a 17-bit long integer, whereas a typical length for n and d will be 1024 bits or more. This makes public-key operations (message encryption, signature verification) much faster than private-key operations (message decryption, signature generation).
In theory, it doesn't have to be. The encryption and decryption algorithms are essentially identical. Given:
d = decryption key
e = encryption key
n = modulus (product of primes)
c = encrypted code group
m = plaintext code group
Then:
Encryption ci = mie (mod n)
Decryption mi = cid (mod n)
The normal algorithm for raising to a power is iterative, so the time taken depends on the size of the exponent. In most cases, the pair works out with the decryption key being (usually considerably) larger than the encryption key.
It is possible to reverse that though. Just for a toy example, consider:
p=17
q=23
n=391
Here's a list of some valid encryption/decryption key pairs for this particular pair of primes:
e = 17, d = 145
e = 19, d = 315
e = 21, d = 285
e = 23, d = 199
e = 25, d = 169
e = 27, d = 339
e = 29, d = 85
e = 31, d = 159
e = 35, d = 171
e = 37, d = 333
e = 39, d = 343
e = 41, d = 249
e = 43, d = 131
e = 45, d = 133
e = 47, d = 15
e = 49, d = 273
e = 51, d = 283
e = 53, d = 93
e = 57, d = 105
e = 59, d = 179
Out of those 20 key pairs, only one has a decryption key smaller than the encryption key. In the other cases, the decryption key ranges from just under twice as big to almost 17 times as large. Of course, when the modulus is tiny like this, it's quick and easy to generate a lot of key pairs, so finding a small decryption key would be fairly easy -- with a real RSA key, however, it's not quite so trivial, and we generally just accept the first pair we find. As you can see from the list above, in that case, you're quite likely to end up with a decryption key that's considerably larger than your encryption key, and therefore decryption will end up slower than encryption. When working with ~100 digit numbers, we'd have to be quite patient to find a pair for which decryption was going to be (even close to) as fast as encryption.
The encryption power is usually chosen to be a prime of the form 2^n+1 (17, 63357) which requires a relatively few multiplication operations. The decryption value will be a much larger number as a consequence, and thus take more work to compute.
There are two factors involved in this:
On the one hand, the public exponent can be chosen to be a small number with only two 1-bits (usually 3, 17 or 65537). This means the RSA encryption operation can be done with a few modular squarings and an addition. This cannot be reversed: If you force the private exponent to be a small number, the security of the system is obviously broken.
On the other hand, the holder of the private key can store some precalculated values derived from the original primes. With those he can use the CRT algorithm to replace the single exponentiation modulo a n-bit number with two exponentiaions modulo a n/2-bit number. This is approximately four times faster than the naive way.
So for RSA key pairs with random public exponents, private key operations can actually be faster. But the effect of choosing a small public exponent is much greater than the effect of the faster algorithm, so encryption is faster in practice.
RSA Laboratories describes why pretty well
In practical applications, it is common to choose a small public exponent for the public key.
...
With the typical modular exponentiation algorithms used to implement the RSA algorithm, public key operations take O(k^2) steps, private key operations take O(k^3) steps
How much longer? Do you have any exact details?
Any way, it make sense that decryption is complicated more than encryption, since the encryption it is not in a symmetric way like 123 => abc and abc > 123.
For more details I suggest starting here.
To read about how the calculatio works, this article seems very good one http://www.di-mgt.com.au/rsa_alg.html
In short "multiply = easy, factor = hard".
Take a look at (http://en.wikipedia.org/wiki/RSA#Encryption) which references optimizations in exponentiation (http://en.wikipedia.org/wiki/Exponentiation_by_squaring#Further_applications)
The best resource I found was the following lecture on cryptography from Princeton (http://www.cs.princeton.edu/courses/archive/spr05/cos126/lectures/22.pdf)
d and e are multiplicatively inverse numbers modulo phi(n). That means that it doesn't matter witch of the two you'll choose for encryption, and witch one for decryption. You just choose once before encryption. If you want fast decryption than you choose the bigger number for encryption. It's that simple.