I'm using Wincrypt for Diffie-Hellman-- can I export the shared secret in plain text? - cryptography

OK-- thanks to Mike, I was able to get Wincrypt to generate a Diffie-Hellman keypair. I figured out out to export the public key, and how to import the other party's public key. According to the docs, upon import of the other party's public key, the shared secret has been computed. Great.
I now need to get ahold of that shared secret, but I don't think its possible. Simply calling CryptExportKey with a type of PLAINTEXTKEYBLOB fails unless I call CryptSetKeyParam to change the algorithm id from CALG_AGREEDKEY_ANY to something... else. But I don't want something else, I want the shared secret. The API, however, seems designed to discourage this.
Any ideas out there? I should note that the problem here is that I'm only writing one side of an implementation of WiFi Protected Setup. So the protocol is defined for me, and the other party is not giving me HCRYPTKEYs.

This looks like what you need...
from: http://msdn.microsoft.com/en-us/library/aa381969(VS.85).aspx
To import a Diffie-Hellman public key and calculate the secret session key
Call the CryptAcquireContext function to get a handle to the Microsoft Diffie-Hellman Cryptographic Provider.
Create a Diffie-Hellman key by calling the CryptGenKey function to create a new key, or by calling the CryptGetUserKey function to retrieve an existing key.
To import the Diffie-Hellman public key into the CSP, call the CryptImportKey function, passing a pointer to the public key BLOB in the pbData parameter, the length of the BLOB in the dwDataLen parameter, and the handle to the Diffie-Hellman key in the hPubKey parameter. This causes the calculation, (Y^X) mod P, to be performed, thus creating the shared, secret key and completing the key exchange. This function call returns a handle to the new, secret, session key in the hKey parameter.
At this point, the imported Diffie-Hellman is of type CALG_AGREEDKEY_ANY. Before the key can be used, it must be converted into a session key type. This is accomplished by calling the CryptSetKeyParam function with dwParam set to KP_ALGID and with pbData set to a pointer to a ALG_ID value that represents a session key, such as CALG_RC4. The key must be converted before using the shared key in the CryptEncrypt or CryptDecrypt function. Calls made to either of these functions prior to converting the key type will fail.
The secret session key is now ready to be used for encryption or decryption.
When the key is no longer needed, destroy the key handle by calling the CryptDestroyKey function.

Related

What if I keep public key and publish the private one?

As far as I've learned, I have to keep the private key secure and publish the public key, so that anyone can encrypt any data using public key and I can decrypt it using my own private key (which nobody has).
The question is, what if I publish the private key and keep the public key? Again the algorithm seems to work: anybody locks the data with the private key (which is published), but no one has the public key (which is kept secure by me).
What makes a public key, a public key? What secure and important data is stored on private key which I should show no one?
For a complete encrypt + decrypt (or sign + verify) process you always need BOTH keys. One for encryption/signing and the other one for decryption/verifying. Which of the keys you use for which operation is (in principle) irrelevant, as long as you use the respective other one for the inverse operation.
So let's assume you used a tool like openssl to generate a key-pair A and B.
When it comes to publishing one of those keys, we have to take into account two aspects
Math: From a pure mathematics point of view (and leaving out the security for a moment), it's irrelevant which of the keys you make public and which you keep private. All processes will work either way.
decrypt(encrypt(data, A), B) == data == decrypt(encrypt(data, B), A)
verify(sign(data, A), B) == OK == verify(sign(data, B), A)
Security: When we take security into account, proving your identity via digital signature is only possible, if you use a key, nobody else can possibly know. For certain crypto systems, it's possible to derive key A from key B, ie there exists a function such that
A = f(B)
but not vice versa, ie there is no function such that
B = f(A)
Thus, the moment you know B, you also know A, but if you only know A, there is no possibility you can derive B.
Thus B is called the private key and must kept private, A is the public key, which can be published. If you do it the other way around, the processes will still work from a mathematical point of view (although most systems will reject your keys), but they are not secure anymore ...
Depending on the system use, the public key may be 'well known'. For example, with RSA, the public key is just your modulus plus the public exponent 65537, while the private key is the modulus plus the private exponent (which is the real secret). So someone who knows the private key also knows the public key pretty much by default. The same is true of most elliptic curve based systems.
In theory one could make an RSA-style system where the public exponent is also hard to determine (say a randomly generated value of enough bits to be non-guessable), in which case it would be more symmetric, but that is not the way the system is usually set up. In any case someone who knows the secret parameters underlying the keys (the factors of the modulus in RSA) can easily determine the public key from the private key or the private key from the public key.
In systems like Diffie-Hellman, the public key is actually derived from the private key by a well-known algorithm (there are no secret paramters other than the private key itself), so in such cases the keys are not symmetrical at all, and anyone who knows the private key can trivially determine the public key.

Changing a Private Ethereum Key into a PEM or HMAC algorithm in NodeJS

I have a private key, which is:
0x66228b427f07b168c7cb1380aa5554403b9e24bf935a9364c89711a306a23ddb
NOTE: The Original Key was the Public Key when the question was posted:
0x6a2043113D5640F9F50dC593D0DcD8CC1c970EB1
I generated it randomly for this question, so don't worry that it's public on the Internet.
I want to use it as the encryption scheme for a JWT token, using the ES256 algorithm.
To get it into my library, I have to have it in one these formats.
secretOrPrivateKey is a string, buffer, or object containing either the secret for HMAC algorithms or the PEM encoded private key for RSA and ECDSA. In case of a private key with passphrase an object { key, passphrase } can be used (based on crypto documentation), in this case be sure you pass the algorithm option.
Is there any easy way to move the hex value to one of these formats? Or, will this not work because I'm not understanding the difference between an Ethereum Private key and a ES256?
Etherium keys are actually ES256K and not ES256 so in this case it might not be possible.
If you need to turn the key in PEM in NodeJS there is a library called key-encoder for this specific purpose. Which can be accomplished with the following code.
var KeyEncoder = require('key-encoder');
console.log(KeyEncoder.default);
let keyEncoder = new KeyEncoder.default('secp256k1')
var pemPrivateKey = keyEncoder.encodePrivate('0x66228b427f07b168c7cb1380aa5554403b9e24bf935a9364c89711a306a23ddb', 'raw', 'pem')
console.log(pemPrivateKey);

Nonce reuse for different recipients?

I'm generating a new random symmetric key and want to pass that to multiple people using crypto_box_easy.
Is it okay to reuse the same (random) nonce for the same message and same sender but for different recipients? Can the same nonce be used for a symmetric encryption with the random key and crypto_secretbox_easy?
As the nonce has to be served along with the encrypted message it can't be hidden anyway, but is reuse across multiple different recipients a problem? If they provide a badly generated public key, can that weaken encryption in a way that other peoples' secret keys could be extracted?
Thanks a lot.
A nonce can be reused as long as a (key, nonce) tuple is not reused.
You're right that reusing a nonce with the same key would result in a catastrophic loss of privacy with a stream cipher like XSalsa20.
The thing is, crypto_box_easy uses the recipients public key to generate a shared secret that is then used with a nonce.
Thus even with a static nonce, the (nonce, key) pair for each recipient will be different.
Although, it's not acceptable to use the same (nonce, key) pair twice, you can use the same nonce for each recipient, but only once.
It's acceptable to use the same nonce once for each recipient using the crypto_box_easy construct ONCE.
It even states this in the libsodium documentation:
The nonce doesn't have to be confidential, but it should be used with just one invocation of crypto_box_easy() for a particular pair of public and secret keys.
i.e. for one message per recipient.

.NET RSA CreateEphemeralKey vs PersistKeyInCsp

I'm trying to learn more about how RSA functions within .NET and came across this helpful post which suggests that by default keys are stored within Windows:
https://stackoverflow.com/a/5845191/1181412
My questions reference the below example code. Assuming the intent is that a one-time key is generated only for the life of the application session.
Question 1: In the below structure, does the PersistKeyInCsp flag need to be set to false every time an RSACryptoServiceProvider is created anywhere within the class even if it is accessing the same CspParameters object?
Question 2: Does setting the CreateEphemeralKey flag on the CspParameters object supersede the need to use PersistKeyInCsp in this example?
Public Class RSACrypto
Private RSAKey As CspParameters
Public Sub New(KeySize As Integer)
MyBase.New()
RSAKey = New CspParameters
Using RSA As New RSACryptoServiceProvider(KeySize, RSAKey)
RSA.PersistKeyInCsp = False
End Using
End Sub
Public Function PublicKey() As Byte()
Using RSA As New RSACryptoServiceProvider(RSAKey)
RSA.PersistKeyInCsp = False
Return RSA.ExportCspBlob(False)
End Using
End Function
End Class
The CreateEphemeralKey flag gets asserted for you if you leave the key container name as null in the CspParameters structure (and you don't assert UseDefaultKeyContainer).
For a key created with CreateEphemeralKey (or implicitly via a null name) the PersistKeyInCsp property has no meaning or effect. For a named (persisted) key it causes the key to be deleted from disk when the object gets Disposed or Finalized. (Note that abnormal termination means the key would never get deleted)
Question 1: In the below structure, does the PersistKeyInCsp flag need to be set to false every time an RSACryptoServiceProvider is created anywhere within the class even if it is accessing the same CspParameters object?
If the key was persisted then the first time you set PersistKeyInCsp=false and called Dispose() (directly or via a using statement), or let the key get garbage collected and finalized, then subsequent accesses would either fail, or create a different key (depending on if the UseExistingKey flag was asserted). So, it is most correct to say "no, you shouldn't do that".
Question 2: Does setting the CreateEphemeralKey flag on the CspParameters object supersede the need to use PersistKeyInCsp in this example?
Yes.
Implicit Question 3: Why doesn't my code work?
In your constructor you had one of three behaviors, depending on the value of CspParameters.KeyContainerName and system state:
KeyContainerName == null:
You created an ephemeral key of size KeySize. Then discarded it. No one will ever know what your key was.
The named key does not exist:
You generated a keypair of size KeySize, saved it to disk, and deleted it. No one will ever know what your key was.
The named key did exist:
You opened the keypair (KeySize was ignored). Then you deleted it off of disk. Hope you didn't need it.
In your PublicKey method you create either a 1024-bit ephemeral key (if RSAKey.KeyContainerName == null) or opened an existing key, or generated a 1024-bit key and persisted it to disk. Then you export the CAPI blob for the public key, and (if ephemeral) discard the key or (if persisted) delete it off of the system. (1024-bit-ness is because you used the CspParameters ctor with no keysize value, so the KeySize value from the ctor is irrelevant)
What you presumably wanted was to save not the CspParameters, but the actual RSA / RSACryptoServiceProvider object.

Naming issue of public and private key

I heard that you can use a private key to encrypt data as a method for digital signing. In other words you can encrypt a message with your private key.
In the text they always seem to say only the public key can encrypt and the private key can decipher the text.
I'm assuming this is a bad choice of words. Is it true that a single instance of a key can do only one or the other, but which key is public or private is not a matter of it's function, but of it's distribution or lack thereof.
For a beginner, the terminology is confusing. RSA can be used for 2 distinct crypto functions: data encryption and digital signatures.
For data encryption, you encrypt data using the recipient's public key; they decrypt it using their private key. Note that due to various limitations of RSA, the "data" that is encrypted and decrypted is usually just a key for a symmetric algorithm.
For digital signatures, you sign the data using your private key; they verify the signature over the data using your public key. Again, various limitations of RSA mean that what is actually operated on by the RSA algorithm is normally a secure hash of the data.
Sometimes the signing operation is called "encrypting with the private key", and the verifying operation is called "decrypting with the public key". I think this just confuses people so I always prefer the terms signing and verifying in this context. Furthermore, "encrypt" and "decrypt" make no sense for other signature algorithms like DSA and ECDSA.
You CAN generate public key from private key.
You CAN'T generate private key from public key (well, you might can, but this is extremely computationally expensive).
That is the difference between the two. They are NOT interchangeable (so, for instance, you SHOULD NOT publish your private key, and keep public key to yourself) because of the way how the algorithms works.
Take for instance RSA. The algorithm base is the problem of integer factorization. You choose two big integers p and q and multiply them to get n = p*q. Then you create public and private key:
Public key: (n, e)
Private key: (p, q, d)
Then:
It is easy to calculate public key from private key:
n = p*q
e = d^(-1) mod φ(n), where φ(n) = (p-1)(q-1)
It is hard to calculate private key from public key - it requires factorization of n to get p and q, which is extremely hard if p and q are big enough.
You release your encryption key to the public, and keep your decryption key private. That way anyone can send you encrypted data that only you can decrypt.
If you did it the other way around, then you would be the only one able to encrypt your data, but anyone could decrpyt it. That makes no sense. If everyone can decrypt your message you might as well send it unencrypted. There is no point encrypted a message and then making the decryption key public.
There are two types encryption one is symmetric another one is asymmetric .In symmetric the key used to encrypt and decrypt is the same . in asymmetric the key used to encrypt is public key and decrypt is private key ..
all works on the principle of a secrecy of the key .In Digital signing commonly used as a part of SSL / TLS protocols uses the asymmetric encryption for the authentication and sharing of the master key which is used further for encrypting the communication line.