Click here to Skip to main content
Licence CPOL
First Posted 19 Nov 2006
Views 52,675
Downloads 298
Bookmarked 13 times

Emulating PBEWithMD5AndDES Encryption under .NET

By | 19 Nov 2006 | Article
A class to provide the same behaviour as Java's PBEWithMD5AndDES encryption algorithm

Introduction

In most ways, .NET's encryption model is pretty good. But when migrating secure applications from Java, the lack of this built in password-based encryption (PBE) is a pain. This article introduces a class that will encrypt data in the same way as Java's PBEWithMD5AndDES algorithm.

The implementation of the algorithm I use is adapted from this article by Michel Gallant.

The Algorithm

As the name suggests, this encryption algorithm uses the DES mechanism with a key generated by MD5 hashing the 'password', combined with a salt string. It allows the input string to be repeatedly MD5-hashed a number of times. The 16-byte MD5 string is then split into two halves, an 8-byte DES key and an 8-byte initial seed for DES.

It obviously makes sense to make use of .NET's DESCryptoServiceProvider to provide the encryption. So this implementation is simply doing the multiple MD5 hash.

The Code

To use this class, simply use:

PKCSKeyProvider kp = new PKCSKeyProvider();
ICryptoTransform crypt = kp.Generate(
      "MyPassword",
      new byte[] { 100, 200, 255, 3},  // salt
      15,             // iterations of MD5 hashing
      1 );  // number of 16-byte segments to create. 
            // 1 to mimic Java behaviour.

Complete class listing:

using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

namespace RedCorona.Cryptography {
    public class PKCSKeyGenerator {
        byte[] key = new byte[8], iv = new byte[8];
        DESCryptoServiceProvider des = new DESCryptoServiceProvider();
        
        public byte[] Key { get { return key; } }
        public byte[] IV { get { return iv; } }
        public ICryptoTransform Encryptor { get { return des.CreateEncryptor(key, iv); } }
        
        public PKCSKeyGenerator(){}
        public PKCSKeyGenerator(String keystring, byte[] salt, 
		int md5iterations, int segments){
            Generate(keystring, salt, md5iterations, segments);
        }
        
        public ICryptoTransform Generate(String keystring, byte[] salt, 
		int md5iterations, int segments){
            int HASHLENGTH = 16;    //MD5 bytes
            byte[] keymaterial = 
	    new byte[HASHLENGTH*segments] ; //to store concatenated Mi hashed results
            
            // --- get secret password bytes ----
            byte[] psbytes;
            psbytes = Encoding.UTF8.GetBytes(keystring);
            
            // --- concatenate salt and pswd bytes into fixed data array ---
            byte[] data00 = new byte[psbytes.Length + salt.Length] ;
            Array.Copy(psbytes, data00, psbytes.Length);  //copy the pswd bytes
            Array.Copy(salt, 0, data00, 
		psbytes.Length, salt.Length) ;//concatenate the salt bytes
            
            // ---- do multi-hashing and concatenate results  D1, D2 ...  
            // into keymaterial bytes ----
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] result = null;
            byte[] hashtarget = new byte[HASHLENGTH + 
		data00.Length];   //fixed length initial hashtarget
            
            for(int j=0; j<segments; j++) {
                // ----  Now hash consecutively for md5iterations times ------
                if(j == 0) result = data00;       //initialize
                else {
                    Array.Copy(result, hashtarget, result.Length);
                    Array.Copy(data00, 0, hashtarget, result.Length, data00.Length) ;
                    result = hashtarget;
                }
                
                for(int i=0; i<md5iterations; i++)
                    result = md5.ComputeHash(result);
                
                Array.Copy(result, 0, keymaterial, j*HASHLENGTH, 
			result.Length);  //concatenate to keymaterial
            }
            
            Array.Copy(keymaterial, 0, key, 0, 8);
            Array.Copy(keymaterial, 8, iv, 0, 8);
            
            return Encryptor;
        }
    }
}

History

  • 19th November, 2006: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

BobJanova



United Kingdom United Kingdom

Member

I'm a recent graduate (MSci) from the University of Cambridge, no longer studying Geology. Programming is a hobby so I get to write all the cool things and not all the boring things Smile | :) . However I now have a job in which I have to do a bit of work with a computer too.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralError in IV property PinmembertHermO782:43 25 Aug '08  
GeneralRe: Error in IV property PinmemberBobJanova11:57 25 Aug '08  
GeneralLicense PinmemberJustin Porter9:45 17 Jul '08  
GeneralRe: License PinmemberBobJanova11:01 17 Jul '08  
GeneralRe: License PinmemberJustin Porter9:12 18 Jul '08  
GeneralNice! PinmemberTitanio2:32 18 Apr '07  
GeneralAdapting for PBEWithMD5AndTripleDES Pinmemberkyoseix8:28 14 Feb '07  
QuestionRe: Adapting for PBEWithMD5AndTripleDES PinmemberBobJanova8:50 14 Feb '07  
QuestionUsing this in .net PinmemberBlahMatt7:23 7 Feb '07  
So I have to ecrypt something using PBEWithMD5AndDES encryption from .net to be decrypted in a java app.
 
In java, to encrypt it I go:
 
private byte[] _salt = {
(byte) 0xc7,
(byte) 0x73,
(byte) 0x21,
(byte) 0x8c,
(byte) 0x7e,
(byte) 0xc8,
(byte) 0xee,
(byte) 0x99 };
 
private int _count = 13;
 
private PBEParameterSpec _pbeParamSpec = new PBEParameterSpec(_salt, _count);
 
public static void main(String[] args)
{
 
Main enc = new Main();
SecretKey key = enc.setKeyString("abcdefghijklm");
byte[] arg;
 
encryptString("4123321123321")
}
 
public String encryptString(String num)
{

byte[] eccbytes = encrypt(setKeyString("abcdefghijklm"), num.getBytes());

StringBuffer encrypted_string_sb = new StringBuffer();
for (int i = 0; i < eccbytes.length; i++) {
char c = (char) (eccbytes[i] & 0Xff);
encrypted_string_sb.append(c);
}

return encrypted_string_sb.toString();
}
 
public byte[] encrypt(SecretKey key, byte[] clearText)
{
byte[] encryptedText = null;

try
{
// Create PBE Cipher
Cipher c = Cipher.getInstance("PBEWithMD5AndDES");

// Create PBE parameter set
//PBEParameterSpec pbeParamSpec = new PBEParameterSpec(_salt, _count);

// Initialize PBE Cipher with key and parameters
c.init(Cipher.ENCRYPT_MODE, key, _pbeParamSpec);

//encryptedText = new String(c.doFinal(clearText.getBytes()));
encryptedText = c.doFinal(clearText);

}
catch (Exception e)
{
System.out.print(e.toString());
}

return encryptedText;
}
 

 

Now, I can't seem to emulate this in .net. I've implemented the class posted here and used the "TransformFinalBlock" method but I've been unable to get the proper results. Would someone mind posting an example of this being implemented.
 
Thanks in advance,
 
Matt
AnswerRe: Using this in .net PinmemberBobJanova7:40 7 Feb '07  
GeneralRe: Using this in .net [modified] PinmemberBlahMatt8:22 7 Feb '07  
GeneralRe: Using this in .net Pinmemberirfanhaleem@hotmail.com1:33 6 Jul '10  
GeneralRe: Using this in .net PinmemberBobJanova1:43 6 Jul '10  
QuestionDecryption? PinmemberAudiedog9:49 29 Nov '06  
AnswerRe: Decryption? PinmemberBobJanova13:27 29 Nov '06  
GeneralRe: Decryption? PinmemberAudiedog6:06 30 Nov '06  
GeneralRe: Decryption? Pinmemberckl_8823:32 6 Jan '07  
GeneralRe: Decryption? Pinmemberckl_8815:02 7 Jan '07  
GeneralRe: Decryption? Pinmembercordobes5:27 13 Oct '08  
GeneralRe: Decryption? Pinmembermascix22:53 13 Nov '08  
GeneralRe: Decryption? Pinmemberjgonzalez7176:38 8 Jul '11  
GeneralMD5 is obsolete PinmemberJan Seda0:30 20 Nov '06  
GeneralRe: MD5 is obsolete PinmemberBobJanova6:06 20 Nov '06  
GeneralRe: MD5 is obsolete PinmemberJan Seda6:16 20 Nov '06  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120529.1 | Last Updated 19 Nov 2006
Article Copyright 2006 by BobJanova
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid