1

Is this possible in C#? How would I accomplish this?

Two-key triple DES is where we encrypt with K1, then decrypt with K2 and finally encrypt again with K1. The keyspace is thus 2 x 56 = 112 bits.

For example, with K1=0x0123456789ABCDEF and K2=0xFEDCBA9876543210 you would set the triple DES key to be 0x0123456789ABCDEFFEDCBA98765432100123456789ABCDEF.

0123456789ABCDEF FEDCBA9876543210 0123456789ABCDEF
|<------K1------>|<------K2------>|<------K3------>|

It accepts A9993E364706816A and the 2 keys that it must use is K1 = 0123456789ABCDEF and K2 = FEDCBA9876543210. The end result must be: 6E5271A3F3F5C418 which I am not getting.

UPDATE:

I am trying to create the concatenated key that I need to use. The 2 keys used above is converted to a byte array and seems to have a length of 16 each. And when the 2 are concatenated then the length is 32. Then my code bombs out. The key has to have a length of 16 or 24. What do I need to do in this case?

UTF8Encoding characterEncoding = new UTF8Encoding();
byte[] accessKey1ByteArray = characterEncoding.GetBytes(accessKey1);
byte[] accessKey2ByteArray = characterEncoding.GetBytes(accessKey2);
byte[] accessKeysArray = accessKey1ByteArray.Concat(accessKey2ByteArray).ToArray();

Here is where I try to set my values:

public byte[] ComputeTripleDesEncryption(byte[] plainText, byte[] key)
{
     TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();

     des.Key = key;
     des.GenerateIV();
     des.Mode = CipherMode.ECB;
     des.Padding = PaddingMode.None;

     ICryptoTransform ic = des.CreateEncryptor();

     byte[] enc = ic.TransformFinalBlock(plainText, 0, plainText.Length);

     return enc;
}

UPDATE 2

Do I need to set the size? The byte array key that I am sending through is K1 + K2 + K1.

The text that I am sending through, do I need convert this to bytes like what you recommended, or can the following also do the trick?

UTF8Encoding characterEncoding = new UTF8Encoding();
byte[] block1ByteArray = characterEncoding.GetBytes(block1);

The value of block1 is: A9993E364706816A.

How I got A9993E364706816A was from my SHA-1 hashed result. The first 16 characters of this hashed result of my string that I want to encode.

Brendan Vogt
  • 25,678
  • 37
  • 146
  • 234
  • Is this algorithm specified by some standard or is it homebrewn? – dtb Oct 04 '11 at 07:37
  • I have no idea because I don't know much of the encryption. See updated post of program flow. – Brendan Vogt Oct 04 '11 at 07:44
  • 1
    You're probably only concerned about getting your task done, but security stuff is really hard to get right. So I'd suggest to investigate if there is a standard that describes the algorithm and write your implementation based on that. Standards are very carefully worded and usually also come with test data, so you can check if your implementation meets the spec. If the algorithm is homebrewn, it's likely broken. Unless it's required to interface with an existing software component, insist on switching to a standardised algorithm. If it is: good luck! :-) – dtb Oct 04 '11 at 07:53
  • Thanks. Let me see what I can do. – Brendan Vogt Oct 04 '11 at 08:00
  • @dtb: This is what I am actually looking for, is this possible? Does .NET actually cater for this? – Brendan Vogt Oct 04 '11 at 09:32
  • Your requirements aren't very clear, I'm afraid. Your example K1 and K2 has 64, not 56 bits. TripleDES works with 128 and 192 bit keys; not sure what "encrypt, then decrypt and encrypt again" means. I'll post some code to concatenate three 64 bit values into one 192 bit value. – dtb Oct 04 '11 at 09:45
  • BTW you also need an Initialization Vector in addition to a key for the TripleDESCryptoServiceProvider class. – dtb Oct 04 '11 at 09:48
  • @dtb: DES and TripleDES have keys that are 64 bits or multiples but only actually use 56 bits of that for security effectively so a 64 bit key will have 56 bits of effective security. This in my mind comes under the heading of use standard libraries and let them worry about implementation. ;-) I think I did read about why but I forgot. :) Triple DES effectively uses three keys (the first and last of which may be duplicates) and does an encrypt/decrypt/encrypt operation with the three keys to form the final encrypted output. – Chris Oct 04 '11 at 10:02
  • @BrendanVogt: why are you worrying abotu the individual components of the key out of interest? Why are you not just agreeing on a 128 bit key? It seems this is being made more complicated by somebody by trying to specify the breakdown of how the TDES is actually working internally... – Chris Oct 04 '11 at 10:03
  • @Chris: I have to admit that I have no idea how TripleDES works internally. For me it's just a black box where you stuff your key, IV and plaintext in and get the ciphertext out. The OP's spec seems to conflate the use of TripleDES in a specific way with the internal details of TripleDES. – dtb Oct 04 '11 at 11:22
  • @dtb: from what I've read what he is describing above is just how TDES works. If you generate a two part key then it will encrypt with the first, decrypt with the second and encrypt with the first again and reverse the process for decrypting. I am worried by why this is being specified somewhere but currently it seems like the details are ignorable in the sense that they are just repetition after you have said "TripleDes with a 128bit key". Though given a mistake is potentially catastrophic here this is also why I suggested the OP read up on the subject quite a lot. – Chris Oct 04 '11 at 12:16

2 Answers2

2

This sounds like you just want to set a 128 bit key for the triple des key.

I believe in this case if you provide a 128 bit key it splits it into two 64 bit keys and uses the first as K1 and K3 and the second as K2 which is exactly what you want.

Unfortunately I can't find a source to quote on this but I did a lot of reading on the subject recently when implementing some crypto stuff myself and finding out about key lengths and this is what I discovered.

If you have K1 and K2 as byte arrays already then you should be able to just use a nice little linq extension method and do:

SymmetricAlgorithm cryptoService = new TripleDESCryptoServiceProvider();
byte[] myKey = K1.Concat(K2).ToArray();
cryptoService.Key = mKey;

That will then do as you want.

In response to your updated part of the question the two keys you have are hexdecimal representations of a sequence of bytes. 0x0123456789ABCDEF is 16 characters of hexdecimal but this is equivalent to 8 bytes of information since it is 4 bits in each character - two making up a byte.

To convert that string to a byte array the following function can be used:

public static byte[] StringToByteArray(String hex)
{
    if (hex.Substring(0,2)=="0x")
    hex = hex.Substring(2);
    int NumberChars = hex.Length;
    byte[] bytes = new byte[NumberChars / 2];
    for (int i = 0; i < NumberChars; i += 2)
        bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
    return bytes;
}

(From How do you convert Byte Array to Hexadecimal String, and vice versa?)

This will then be used like this:

string K1="0x0123456789ABCDEF";
string K2="0xFEDCBA9876543210";
byte[] key = StringToByteArray(K1).Concat(StringToByteArray(K2)).ToArray();

When implementing TDES you will need to agree a key, Block Cipher mode, Padding method and in most Block modes you will need an initialisation Vector. You'll possibly also want to use a Message Authentication Code.

To get an initialisation vector you'll want to do something like:

cryptoService.GenerateIV();
byte[] iv = cryptoService.IV;

I strongly advise reading pages on encryption to understand better what the various things you are doing actually are rather than just writing the code. It will make you more confident in your security and make you sound more confident while dealing with others. I've taken the liberty of including some links, most of which can be found by just googling.

Useful links:

http://en.wikipedia.org/wiki/Initialization_vector - all about initialisation vectors

http://en.wikipedia.org/wiki/Triple_DES - on the TDES algorithm

http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation - How consecutive blocks of data interact with each other.

http://en.wikipedia.org/wiki/Padding_%28cryptography%29 - Not massively important except there are different ways of padding and both sides need to be using the same one (of course).

http://chargen.matasano.com/chargen/2009/7/22/if-youre-typing-the-letters-a-e-s-into-your-code-youre-doing.html - An excellent and amusing commentary on the use of encryption and where there are weaknesses and what encryption can and cannot do.

http://en.wikipedia.org/wiki/Message_authentication_code - How to confirm that your message hasn't been tampered with

Community
  • 1
  • 1
Chris
  • 27,210
  • 6
  • 71
  • 92
  • Thanks so far. Do you also need an initailization vestor? I don't have one? How do I get one? And do you also use TripleDESCryptoServiceProvider? – Brendan Vogt Oct 04 '11 at 10:03
  • @BrendanVogt: updated post with how to get the byte arrays from the string formats that you have. – Chris Oct 04 '11 at 12:44
  • I feel I should ask why you are transmitting the first 16 characters of a string representation of a hash of something? The hash classes return a byte array which is suitable for encrypting directly. Converting this to a string and then back to a byte array seems slightly silly. Also I am not sure why you are wanting to just send part of a computed hash to somebody securely. A hash is not really sensitive data since you can't go from a hash to the original item. As to how you get the bytes, it doesn't make much difference, as long as the other end knows how to deal with them when decrypting. – Chris Oct 04 '11 at 13:45
  • These are requirements that was given to me. I'm not going against it. How it currently works is that I break up the hashed string into 3 parts. The result is used with K1 and K2 for a another 3DES until repeated 3 times until I have a MAC. – Brendan Vogt Oct 05 '11 at 05:56
2

To encrypt/decrypt data with the TripleDES algorithm, you can use the TripleDESCryptoServiceProvider Class. The algorithm supports key lengths from 128 bits to 192 bits in increments of 64 bits.

If you have two 64-bit keys

byte[] k1 = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
byte[] k2 = new byte[] { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 };

and want to concatenate k1, k2 and k1 again to a 192-bit key, you can do this as follows:

byte[] key = new byte[K1.Length + K2.Length + K1.Length];
Buffer.BlockCopy(k1, 0, result,  0, 8);
Buffer.BlockCopy(k2, 0, result,  8, 8);
Buffer.BlockCopy(k1, 0, result, 16, 8);

Note that, in addition to the key, you also need an initialization vector:

byte[] iv = // ...

Example:

byte[] data = new byte[] { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A };

using (var csp    = new TripleDESCryptoServiceProvider())
using (var enc    = csp.CreateEncryptor(key, iv))
using (var stream = new MemoryStream())
using (var crypto = new CryptoStream(stream, enc, CryptoStreamMode.Write))
{
    crypto.Write(data, 0, data.Length);
}
dtb
  • 213,145
  • 36
  • 401
  • 431
  • If you can, please provide a solution how you would implement the above in the triple DES encryption that I am looking for? – Brendan Vogt Oct 04 '11 at 09:53
  • Please see my updated post. Those are the requirements that I have. – Brendan Vogt Oct 04 '11 at 10:01
  • What would be my initialisation vector? Nothing was specified in my requirements doc? – Brendan Vogt Oct 04 '11 at 10:05
  • 1
    +1 Peeps, wouldn't it only be polite to _at least upvote_ an answer showing such excellent and concise example code, before just continuing to make requests? Good answers must be appreciated for SO to work – sehe Oct 04 '11 at 10:09
  • @sehe: Assuming you +1ed the original answer I'm amused that somebody +1ed you but not the answer. ;-) – Chris Oct 04 '11 at 10:31
  • @dtb: its worth noting how to get the IV. Crucially it should not be static whcih is why the SymetricAlgorithm class defines a GenerateIV method (see my answer for the admittedly simple usage). Also if it is encrypting bytes rather than a stream then you want TransformFinalBlock if you are going to put in the full usage (I decided it seemed silly for both of us to be updating our good answers in competition). `ICryptoTransform cTransform = cryptoService.CreateEncryptor(); byte[] resultArray = cTransform.TransformFinalBlock(toBeEncryptedArray, 0, toBeEncryptedArray.Length);` – Chris Oct 04 '11 at 10:37
  • @Chris: I still suspect that the OP's code has to interface with some existing other component, so just using a randomly generated IV probably doesn't work, if there is no specified way for the recipient to obtain the IV. – dtb Oct 04 '11 at 11:24
  • @dtb: this is true though if he is encrypting then he would likely be the one generating the IV and passing it on. If he is decrypting though then you are right that he should be getting it from somewhere else. Generally an IVs most important trait is being random and I can't imagine that somebody else can pass a better IV than is generated by the crypto methods designed to do as such. Though I guess if there is a hardware random number generator somewhere then you might want to get stuff like this from there. :) – Chris Oct 04 '11 at 12:18