G
gcrasher
I've been trying to figure this out for a while and don't understand
what's going on.
I'm using RSA algorithm to implement a licensing strategy in which the
hardware ID is sent to me, encrypted, and sent back to be decrypted on
the device, thus verifying that I actually created the data. This
requires encrypting on the desktop using my secure private key, and
unencrypting on the device using a public key.
For the device I'm using the OpenNET.Security.Cryptography classes and
System.Security.Cryptography classes on the desktop (for my license
creation utility).
I'm not understanding how the key containers work on the device using
OpenNETCF classes and I'm guessing that is part of my problem. Unless
I create the public/private keys on the device, I get a NTE_BAD_KEY
error when trying to decrypt on the device. When a new key set is
generated on the device (not to be used, just to *reset* the device so
I can attempt to provide my own public key), the old public key no
longer decrypts the old data it used to decrypt. If I use the keys the
device last generated then my code works fine.
It seems that when creating the keys on the device, the public key is
stored somehow and even though I am specifying my own public key, the
OpenNETCF classes somehow are utilizing or checking that container
(maybe?). This decryption will need to occur on devices where the keys
were not generated. How is it possible for me to provide the public
key myself? Anyone have any ideas how I can get this working the way I
need to?
Thanks!
I've included the code being used below:
--------------------------------------
---Create key pair using the device---
--------------------------------------
using OpenNET.Security.Cryptography;
RSACryptoServiceProvider rsa = new
RSACryptoServiceProvider(OpenNETCF.Security.Cryptography.NativeMethods.KeySpec.KEYEXCHANGE,
true);
// Save the public key to pubkey.txt
FileStream fs = new FileStream("pubkey.txt", FileMode.Create);
StreamWriter sw = new StreamWriter(fs);
sw.Write(rsa.ToXmlString(false));
// Save the private key to privkey.txt
fs = new FileStream("privkey.txt", FileMode.Create);
sw = new StreamWriter(fs);
sw.Write(rsa.ToXmlString(true));
---------------------------------
---Encrypt data on the desktop---
---------------------------------
using System.Security.Cryptography;
string plain = "Text to be encrypted.";
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
// Get the XML string from the privkey.txt file
FileStream fs = new FileStream("privkey.txt", FileMode.Open);
StreamReader sr = new StreamReader(fs);
string privateKeyString = sr.ReadToEnd();
// Load private key
rsa.FromXmlString(privateKeyString);
// convert the plaintext to a byte array using UTF-8
UTF8Encoding utf8 = new UTF8Encoding();
byte[] plaintext = utf8.GetBytes(plain);
// Encrypt the plaintext
byte[] ciphertext = rsa.Encrypt(plaintext, false);
// Create encrypted output file.
FileStream ciphertextfile = new FileStream(outputFile,
FileMode.Create);
ciphertextfile.Write(ciphertext, 0, ciphertext.Length);
-----------------------------------
---Decrypt data using the device---
-----------------------------------
using OpenNET.Security.Cryptography;
string publicKey =
<RSAKeyValue><Modulus>qe9vUaTreNvSRynh36T4b74VRqdCOEHhX1xrkdmrwkRBs5yhRBAD+BM2yB5kL7aA
BLvW+biQAZCfVDnh3wIMUuzd9pwYaU8FtL8pnq7EEu6ps3a5C7M63fZTj1slFSiTMiGY6rCMOCajSFeOEULMPF
Ukj5wJ8WBjWWtRU1HYt/U=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
UTF8Encoding utf8 = new UTF8Encoding();
// Read encrypted file.
byte[] encryptedBytes = Utility.ReadFile(encryptedFileName);
// Set public key.
rsa.FromXmlString(publicKey);
// Decrypt bytes.
string unencryptedString = new
String(utf8.GetChars(rsa.DecryptValue(encryptedBytes)));
what's going on.
I'm using RSA algorithm to implement a licensing strategy in which the
hardware ID is sent to me, encrypted, and sent back to be decrypted on
the device, thus verifying that I actually created the data. This
requires encrypting on the desktop using my secure private key, and
unencrypting on the device using a public key.
For the device I'm using the OpenNET.Security.Cryptography classes and
System.Security.Cryptography classes on the desktop (for my license
creation utility).
I'm not understanding how the key containers work on the device using
OpenNETCF classes and I'm guessing that is part of my problem. Unless
I create the public/private keys on the device, I get a NTE_BAD_KEY
error when trying to decrypt on the device. When a new key set is
generated on the device (not to be used, just to *reset* the device so
I can attempt to provide my own public key), the old public key no
longer decrypts the old data it used to decrypt. If I use the keys the
device last generated then my code works fine.
It seems that when creating the keys on the device, the public key is
stored somehow and even though I am specifying my own public key, the
OpenNETCF classes somehow are utilizing or checking that container
(maybe?). This decryption will need to occur on devices where the keys
were not generated. How is it possible for me to provide the public
key myself? Anyone have any ideas how I can get this working the way I
need to?
Thanks!
I've included the code being used below:
--------------------------------------
---Create key pair using the device---
--------------------------------------
using OpenNET.Security.Cryptography;
RSACryptoServiceProvider rsa = new
RSACryptoServiceProvider(OpenNETCF.Security.Cryptography.NativeMethods.KeySpec.KEYEXCHANGE,
true);
// Save the public key to pubkey.txt
FileStream fs = new FileStream("pubkey.txt", FileMode.Create);
StreamWriter sw = new StreamWriter(fs);
sw.Write(rsa.ToXmlString(false));
// Save the private key to privkey.txt
fs = new FileStream("privkey.txt", FileMode.Create);
sw = new StreamWriter(fs);
sw.Write(rsa.ToXmlString(true));
---------------------------------
---Encrypt data on the desktop---
---------------------------------
using System.Security.Cryptography;
string plain = "Text to be encrypted.";
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
// Get the XML string from the privkey.txt file
FileStream fs = new FileStream("privkey.txt", FileMode.Open);
StreamReader sr = new StreamReader(fs);
string privateKeyString = sr.ReadToEnd();
// Load private key
rsa.FromXmlString(privateKeyString);
// convert the plaintext to a byte array using UTF-8
UTF8Encoding utf8 = new UTF8Encoding();
byte[] plaintext = utf8.GetBytes(plain);
// Encrypt the plaintext
byte[] ciphertext = rsa.Encrypt(plaintext, false);
// Create encrypted output file.
FileStream ciphertextfile = new FileStream(outputFile,
FileMode.Create);
ciphertextfile.Write(ciphertext, 0, ciphertext.Length);
-----------------------------------
---Decrypt data using the device---
-----------------------------------
using OpenNET.Security.Cryptography;
string publicKey =
<RSAKeyValue><Modulus>qe9vUaTreNvSRynh36T4b74VRqdCOEHhX1xrkdmrwkRBs5yhRBAD+BM2yB5kL7aA
BLvW+biQAZCfVDnh3wIMUuzd9pwYaU8FtL8pnq7EEu6ps3a5C7M63fZTj1slFSiTMiGY6rCMOCajSFeOEULMPF
Ukj5wJ8WBjWWtRU1HYt/U=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
UTF8Encoding utf8 = new UTF8Encoding();
// Read encrypted file.
byte[] encryptedBytes = Utility.ReadFile(encryptedFileName);
// Set public key.
rsa.FromXmlString(publicKey);
// Decrypt bytes.
string unencryptedString = new
String(utf8.GetChars(rsa.DecryptValue(encryptedBytes)));