3DES with .cer public key? - c#

I'm no crypto expert, but as I understand it, 3DES is a symmetric encryption algorithm, which means it doesnt use public/private keys.
Nevertheless, I have been tasked with encrypting data using a public key, (specifically, a .CER file).
If you ignore the whole symmetric/asymmetric thang, I should just be able to use the key data from the public key as the TripleDES key.
However, I'm having difficulty extracting the key bytes from the .CER file.
This is the code as it stands..
TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();
X509Certificate2 cert = new X509Certificate2(#"c:\temp\whatever.cer");
cryptoProvider.Key = cert.PublicKey.Key.
The simplest method I can find to extract the raw key bytes from the certificate is ToXmlString(bool), and then doing some hacky substringing upon the returned string.
However, this seems so hackish I feel I must be missing a simpler, more obvious way to do it.
Am I missing a simpler way to use a .cer file to provide the key data to the C# 3DES crypto class, or is hacking it out of the certificate xml string really the best way to go about this?

It's not a good idea to use keys generated for asymmetric cryptography for symmetric cryptography. There's nothing preventing you from coming up with a way of using a public key as an encryption key for 3DES, but the end result will be that anyone having access to the public key (and this means everyone!) will be able to decrypt your ciphertext.

cryptoProvider.Key = cert.GetPublicKey()?

Encrypting large amounts of data with asymmetric cryptography is not the way to go. Instead, encrypt the data with a symmetric algorithm and encrypt the symmetric key (and IV) with your public key.
This page from MSDN really helped me get going with .Net symmetric cryptography.

The real problem here is that the public key is, well, public. Meaning freely available, meaning it's providing zero security of encryption.
Heck, anyone on this thread has all the information they need to decrypt everything. So do googlers.
Please try to encourage your users not to use public key data like that. At the very least, get them to give a password or some other slightly-more-secure chunk you can use to generate a consistent key.
One more thing. Certificate keys vary in size. It can probably handle throwing away extra bytes in the key, but you'll probably get an Array Index / Out Of Bounds exception if the key happens to be shorter than the 3DES key needs. I doubt that'll happen, 3DES only needs 56bits, and cert keys are almost always 256bits or larger.

I think what you are missing is converting the bytes from the string containing the key-bytes.
Hope the method FromBase64String will help you:
byte[] keyBytes = Convert.FromBase64String(sourceString);

Related

How to encrypt generated RSA private key and decrypt in c#

I have seen articles regarding encrypt/decrypt data using Private/Public key. All I want to do is to just encrypt a generated RSA private key already stored in a file. I have been browsing widely to get an idea how it can be done but with no luck.I presume my question is rather an unusual one. Please help!
First, you need a *Key derivation function, to turn your password into a symmetric key which you can use to encrypt your private key. If you solely use the .NET framework, you should use the Rfc2898DeriveBytes class for that. If you are able to use BouncyCastle, then SCrypt would be preferred.
Then you can encrypt your key, prefreably using the AES algorithm.
Some usable code sample can be found in this answer

Decryption-Only method in C#

I'm looking for a secured way to implement a license file for my application, with flags and features. I read about Asymmetric key mechanism in C#, but the RSA purpose is little opposite from what I need.
I want to generate a license file: encrypted cipher. The application would have the key to decrypt the file - but wont have the ability to re-encrypt it. Everywhere I checked, the example shows how party A generates public and private keys and passes the public key to party B so it can use it for encryption. It's probably there between the lines, but I can't see it.
I checked this one: Encrypting and Decrypting
I can find a way to use the code I see to implement it, but I'm not sure it's really secured.
You can still use asymmetric encryption: generate a public-private key pair, encrypt with the private key, and the client (the "application" as you mentioned) can decrypt it with the public key.
Of course, a public key (and the private key too) can be used for both encrypting and decrypting.
But re-encrypting plain text with a public key would generate a completely different cypher than a cypher encrypted using a private key. Decrypting and re-encrypting with the same key would produce a different result, and so it's useless.
What dcastro said above is absolutely correct, and you should give him credit. I just want to add to it, but can't yet comment. If you encrypt the license information with our private key, and distrute your public key with the application, you would be able to decrypt the license information. Without the private key, it wouldn't be possible to re-encrypt a different version of the license that could be decrypted with the public key without using the private key.
Asymetric encryption works like this.
Information encrypted with public key can only be decrypted using the private key.
Information encrypted with the private key can only be decrypted using the public key.
Now for the kicker.. You're probably going to want to encrypt your license with a symmetric algorithm, and encrypt the key needed to decrypt it with the asymmetric algorithm. This way the length of your license data isn't limited by the asymmetric and the symmetric key can be customer specific.
Like I said, give the credit to dcastro.

How / Should I Encrypt Variable Size Data with RSA (RSACryptoServiceProvider)

In my research I have found mixed messages on this subject so I'm looking for expertise to explain the best approach to encrypting variable amounts of data.
Requirements:
[Edit: Adding additional requirement #3 in response to comment]
I would like to use RSA for the public/private key encryption scheme
so I can distribute the public key to an application that should
encrypt data but should not know how to decrypt it
I need to support data lengths from 16 characters (credit card
number) to kilobytes (serialized objects) and beyond. Most of the
data I encrypt will be small (credit cards, addresses, etc).
This is for encrypting data at rest.
Options I'm Aware Of:
RSA-ONLY: Use RSACryptoServiceProvider to encrypt all data using public key.
Iterate through the data in blocks that are less than the key size
minus padding.
HYBRID: Use AesCryptoServiceProvider to encrypt the data, calling
.GenerateKey() and .GenerateIV() to generate a random key and IV.
Then use RSACryptoServiceProvider to encrypt the above key and IV
and prepend or append that to the data.
It seems to my the Hybrid approach gives me the best of both worlds. Strong block cipher (AES) and distributed public key (RSA).
What are the pros and cons of these approaches? What is the standard? Surprisingly I have not found much opinion or information on the subject and would appreciate any references you might have.
Bonus:
I am rolling my own for various reasons including corporate licensing restrictions but I'm curious if there is a good standard opensource approach for C#.
in most cases RSA is used to encrypt a symetric key (you don't really need to encrypt the IV, but hey...)
if you use RSA for encryption of data (instead of a key) you might run into the ECB (Electronic Code Book mode) problem that is known in the context of symetric block cyphers: for a given key, a clear-text is always mapped to the same cypher-text ... that alone doesn't help in breaking the encryption, but it can leak information since an attacker can identify which data packages contain the same clear-texts
i'd choose the hybrid approach, because it's suitable for arbitrary sized data, and won't be prone to this information leak unless you choose ECB for the mode of operation (CBC - Cypher Block Chaining mode - should do)
If you just want to use RSA to store a small amount of data, smaller than the number of bits in the key, you can pad the input data with random numbers. There are several padding schemes listed at https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Padding

Encryption algorithms that don't use a key

I need a simple encryption algorithm that doesn't use a key.
Which ones do you guys recommend?
How about if I use the built in encryption method that forms authentication has? (I forget the method/namespace for it).
Every symmetrical encryption scheme has a key. If you're looking for an encryption scheme where you don't manage the key, you might look into the Data Protection API, exposed in .NET (2.0 and above) as the System.Security.Cryptography.ProtectedData class. It provides symmetric encryption of arbitrary data, using the credentials of the machine or (better) the user, as the encryption key.
byte[] plaintextBytes = GetDataToProtect();
byte[] encodedBytes = ProtectedData.Protect(plaintextBytes
, null
, DataProtectionScope.CurrentUser);
See my other answer here for more detail.
Something outside of the thing being encrypted needs to be used to do encryption, if only because you need that thing to decrypt it later. This external thing is a key. There is no useful encryption without a key. There is only hashing.
What you are calling encryption is simply obfuscation. Even then its going to be encryption where the key is embedded in the algorithm. You'll have to provide at least a simple use case for this before you're going to get any kind of reasonable answer.
rot13 uses a key that's already in the algorithm. That's the closest I think you're going to get.
As an aside to the talks about no key = no encryption...
Maybe what you're really after is automatic and safe key creation and exchange with no user interaction. This can be done by the use of asymmetric encryption, and it works like this:
Scenario: A needs to send a message to B, and wants to make sure no man-in-the middle can read the message.
A and B initiate a conversation like this:
A asks B for B's public key.
B generates a public/private key pair, and sends the public key to A.
A uses the public key to encrypt the message, and sends the message.
B receives the message, and decrypts it with its private key.
This works since the message is encrypted with a public key, can only be decrypted with the corresponding private key. So the public key doesn't have to be secret. If man-in-the-middle picks up the public key, he can't use it to decrypt the message.
You'll probably find tons of information about this if you google for asymmetric encryption...
Fundamentally, ciphers are a way to let Alice tell something to Bob that Eve can't figure out even if she overhears.
This means that there has to be some way for the ciphertext to distinguish Bob from Eve.
Usually, this is a key. Nowadays, it can be a symmetric cipher key that Alice gives to Bob and not Eve somehow, or an asymmetric cipher key that Bob broadcasts so that anybody can encrypt a message for him that only he can read (often used as a way to transmit a symmetric cipher key).
An algorithm can serve as a key, but algorithms are really inconvenient to distribute and keep secret. It's better just to use a standard key.
You could simply obfuscate the plaintext, if you're willing to count on Bob being motivated to read the message and Eve not be. You could do that by zipping a file, for example. Eve couldn't just read it, she'd have to unzip it. This is usually done to prevent Eve from accidentally reading something meant for Bob, on the assumption that Eve is honorable but may make occasional mistakes. The example popping into my mind is the CVS password file; it will prevent a sysadmin from seeing the password at a glance, but it's "the moral equivalent of rot13" if somebody actually wants to read it.
So, to give you a useful answer, we need to know what you want to use this for. How sensitive is the data? How likely is it to fall into unfriendly hands? Who do you want to be able to read it?
BTW, never roll your own cryptography. It's real easy to get something wrong and real hard to notice it. Use standard implementations of standard algorithms.
The problem with keyless encryption is that once it's broken, it's broken for everyone. Take MicroSoft Script Encoder as an example. Once one person figured out how to reverse the encryption and published it, the encryption was broken for everyone (see comments for details on how this isn't as bad as it sounds in this case).
That being said, you can use any keyed algorithm and keep the key a secret and you'll get the same (bad) effect.
If you're really after obfuscation, you can use the PasswordDeriveBytes class to create a key from a password. Then use the key in e.g. AES.

Can I use the assemblies PublicKey to decrypt a string encrypted with the corresponding PrivateKey?

Signing an assembly in .NET involves a public/private key pair. As far as I can tell from what I've read .NET uses the RSA algorithm and the private key to sign the assembly, checking it with the embedded public key.
I know how to retrieve the public key (Assembly.PublicKey). I was wondering, if that key could be used to decrypt a short string that contains some data encrypted with the private key.
The docs I've read so far (e.g.) seem to imply that only the other way round is possible: That I would have to use the public key to encrypt and the private key to decrypt - but I don't really want to include that in the assembly, do I.
I guess it would be ok, if I just signed the string. But how?
I'm a bit at a loss how to start this. Does anybody have a code snippet?
Also, encrypting / signing of the small string would ideally happen in PHP, since I want to offload that to a web server and all we have so far is your generic PHP/MySQL hosted website.
Use Case: I'm trying to come up with a lightweight licensing scheme for a software we are about to release to beta testers. Since the software will probably be freeware, all we really want to achieve is
know who has the software installed (email address)
let the software expire after a given period, after which the user will have to get a new license
this is as easy as filling out a form and waiting for an automated email with the key to arrive
we are trying to reduce the likelyhood of old versions coming back to bite our reputation / haunt us
Being able to encrypt a tuple (expiry date, fingerprint) and decrypt that at startup would make an easy licensing module: The first time the application is started, the user is asked for email address, name, organisation. This information is posted to the webserver along with an md5 fingerprint of some system info (nic, computer name, assembly major and minor version). The webserver answers by email (checks validity of email address) with an encrypted version of the tuple (expiry date, fingerprint) that is then saved to disk. On startup, this can be decrypted and compared with current date and regenerated fingerprint.
EDIT: OK, so I don't have all the answers to my question yet. But it looks like .NET won't make it easy to use the private key for encryption (if that is at all possible, the answers don't really agree on that).
The route I will take is this (based on my use case):
I will use the private key to sign the license.
I will use the public key to verify the license was signed by the private key
I will post another question aimed at PHP devs on how to use the .NET keys (produced by sn.exe) to sign some text
I am not really worried about the user seeing the license, as it is a hash anyway and computed from stuff he allready knows. All I want is to make it too hard to be worth any bother for your typical building architect to copy my software without me knowing (remember, the software will be freeware - all I want is a paper trail of who has it installed...)
Thank you very much for your answers.
You cannot decrypt using the public key. That way, the whole point of "public" would be lost.
(You might, however, be able to sign something using the private key, then verify the signature using the public key. That's what the framework uses the keys for - the assembly is signed, and the public key is used to verify the signature.)
This can be done using SignedXml http://msdn.microsoft.com/en-us/library/ms229745.aspx. At a lower level you can prob use RSAPKCS1SignatureDeformatter and RSAPKCS1SignatureFormatter. These work by encrypting a hash of the data then comparing the data with the (decrypted) hash the other end. I believe the hashing is used because private key encryption can only handle small data. Not sure about reusing the assembly public key, if it is causing problems just use a separate key pair.
Word of warning, check out this as these classes can result in 20 second hang ups! http://www.pcreview.co.uk/forums/thread-3428177.php
This approach is vulnerable to the signature verification code being tampered with using Reflexil but that is another matter.
I wrote the following but rereading I think you already got this: You aren't really trying to encrypt or hide data from the user, you want to stop them from creating or tampering the license. You are right that a public private key encryption algorithm can be used for this. This is known as Signing using a private key (server side license generation). And verification of the signature using a public key (license checking in the app). I mention this terminology as it'll help with research.
Not in .NET.
In many traditional public-key encryption algorithm, like RSA, you can encrypt and decrypt both ways, typically one way is called "encryption" and the other "signing", even though you actually end up with an encrypted version of something both ways.
However, in .NET the RSA implementation has been crippled, and when signing will only produce digests of the input, not the full processed information.
It seems there's some disagreement about what can and cannot be done with RSA, so let me edit my answer to be more specific.
I'm talking about RSA math, not any particular RSA implementation.
RSA math allows you to encode information either of the two keys (private or public), and the encoded data can only be decoded with the other of the two keys.
Typically, you encode with a public key, encrypting the information, and decode it with the private key, decrypting the information. Or, you take a hash of the information, encode it with the private key, signing the hash, and decode the hash with the public key, in order to compare and verify the signature.
Typical implementations does not allow one to do full encoding of data from private to public, only by hashing the data, but the math behind RSA fully allows this.
In RSA Public keys are used for encryption, private keys are used for decryption. You can't use a public key to decrypt anything...
In RSA the only actual difference between a public key and a private key is which one you keep secret.
So you can use a public key as the encryption key and decrypt with the private key, or use the private key as the encryption key and decrypt with the public key.
Encrypting with the private key is used for digital signatures (anybody can decode with the public key).
But as #Lasse V. Karlsen pointed out, .Net might make it more difficult than it should be...
I think both direction are possible encrypt with public and decrypt with private and encrypt with private key. The second is the way how digital signature works.
Warning! This answer is wrong but I'm going to leave it here none-the-less because the series of comments attached are, I think of sufficient interest to others to keep the answer around. Ok it makes me look like an idiot but thats nothing new to me ;) Vote as you wish.
A public key can be used to:-
Encrypt something that can only be decrypted with the private key
Authenticate something signed with the private key
It can not be used to decrypt something to encrypted by a private key. Its for this reason that the Public/Private key system is refered to as an Asymetric system.

Categories