How to inplement C# DESCryptoServiceProvider in Go Lang?

906 views
Skip to first unread message

tuanhoanganh

unread,
Oct 3, 2015, 1:38:18 PM10/3/15
to golang-nuts
Hello. How to inplement C# DESCryptoServiceProvider in Go Lang? I have Decrypt in C# and want Encrypt in go lang.
Here is my C#

 public class Cryptography
 {
  [DebuggerStepThrough()]
  public static string MD5(string strHash)
  {
   using (HashAlgorithm hashAlg = HashAlgorithm.Create("MD5"))
   {
    // Convert the password string, provided as the second command
    // line argument, to an array of bytes.
    byte[] pwordData = Encoding.Unicode.GetBytes(strHash);

    // Generate the hash code of the password.
    byte[] hash = hashAlg.ComputeHash(pwordData);

    // Display the hash code of the password to the console.
    return BitConverter.ToString(hash);
   }
  }

  //DES Key size is 64 bit or 8 byte
  private static readonly string strDefaultKey = "XXXX";
  private static readonly byte[] DefaultIV = new byte[8] { XX, XX, XX, XX, XX, XX, XX, XX };
  private static readonly byte[] Salt = new byte[8] { XX, XX, XX, XX, XX, XX, XX, XX };

  [DebuggerStepThrough()]
  private static byte[] GetKey(string strkey)
  {
   byte[] key = Encoding.Unicode.GetBytes(strkey);
   PasswordDeriveBytes pdb = new PasswordDeriveBytes(key, Salt);
   return pdb.GetBytes(8);
  }
  
  #region Encrypt
  [DebuggerStepThrough()]
  public static string Encrypt(string str, string strkey)
  {
   SymmetricAlgorithm algorithm = new DESCryptoServiceProvider();
   
   algorithm.IV = DefaultIV;
   algorithm.Key = strkey == null ? GetKey(strDefaultKey) : GetKey(strkey);

   MemoryStream ms = new MemoryStream();
   CryptoStream cs = new CryptoStream(ms, algorithm.CreateEncryptor(), CryptoStreamMode.Write);

   UnicodeEncoding ae = new UnicodeEncoding();
   byte[] plainBytes = ae.GetBytes(str);

   cs.Write(plainBytes,0,plainBytes.Length);
   cs.FlushFinalBlock();
   
   byte[] crytoBytes = ms.ToArray();
   return Convert.ToBase64String(crytoBytes);
  }
  #endregion

  #region Decrypt
  [DebuggerStepThrough()]
  public static string Decrypt(string str, string strkey)
  {
   byte[] cryptoBytes = Convert.FromBase64String(str);
   return Decrypt(cryptoBytes, strkey);
  }

  [DebuggerStepThrough()]
  public static string Decrypt(byte[] str, string strkey)
  {
   SymmetricAlgorithm algorithm = new DESCryptoServiceProvider();

   algorithm.IV = DefaultIV;
   algorithm.Key = strkey == null ? GetKey(strDefaultKey) : GetKey(strkey);
   
   MemoryStream ms = new MemoryStream(str);
   CryptoStream cs = new CryptoStream(ms, algorithm.CreateDecryptor(), CryptoStreamMode.Read);
   byte[] plainBytes = new byte[str.Length];
   cs.Read(plainBytes, 0, str.Length);
   
   UnicodeEncoding ae = new UnicodeEncoding();
   return ae.GetString(plainBytes).Replace("\0","");
  }
  #endregion
 }


Skip Tavakkolian

unread,
Oct 3, 2015, 9:06:40 PM10/3/15
to tuanhoanganh, golang-nuts
i think the StreamWriter example in crypto/cipher package (link below) is close to what you want. instead of using aes.NewCipher in the example, you'll need to use des.NewCipher (crypto/des). you will want to have a base64 encoder (encoding/base64) instead of a File writer. also the mode of operation (OFB in the example) should match on both sides (e.g. algorithm.Mode = OFB, etc)

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

tuanhoanganh

unread,
Oct 3, 2015, 11:04:03 PM10/3/15
to Skip Tavakkolian, golang-nuts
@Skip Tavakkolian

Thanks for your answer. But I don't know how to implement PasswordDeriveBytes in golang.
Go has pbkdf2 but PasswordDeriveBytes use PBKDF1 (http://stackoverflow.com/questions/2121047/java-encode-and-net-decode)

Skip Tavakkolian

unread,
Oct 4, 2015, 10:56:23 AM10/4/15
to tuanhoanganh, golang-nuts
my cursory review of RFC-2898 leads me to believe that pbkdf2.Key() with proper keylen and hash function can produce pbkdf1 keys.


tuanhoanganh

unread,
Oct 11, 2015, 2:56:51 AM10/11/15
to Skip Tavakkolian, golang-nuts
 @Skip Tavakkolian

my cursory review of RFC-2898 leads me to believe that pbkdf2.Key() with proper keylen and hash function can produce pbkdf1 keys.

Here is my test pbkdf2 but don't has same result as c#

=== crypt.go ===
package crypt

import (
    "golang.org/x/crypto/pbkdf2"
     "crypto/sha1"
)

var strDefaultKey string="65EA7902-C2A0-436E-8345-22260DC104C0";
var defaultIV = []byte{43, 56, 32, 32, 32, 23, 22, 32}
var salt = []byte{55, 156, 33, 56, 100, 43, 45, 43 }

func GetDefaultPass() string {
    return strDefaultKey
}

func GetDefaultPassByte() []byte {
    return []byte(strDefaultKey)
}

func GetKey(password string) []byte {
    return pbkdf2.Key([]byte(password), salt, 100, 8, sha1.New)
}
 
=== crypt_test.go ===
package crypt_tests

import (
    "erpvietnam/fhc/core"
    "testing"
    "bytes"
    "fmt"
)

func TestGetDefaultPassByte(t *testing.T) {
    ok := []byte{54, 53, 69, 65, 55, 57, 48, 50, 45, 67, 50, 65, 48, 45, 52, 51, 54, 69, 45, 56, 51, 52, 53, 45, 50, 50, 50, 54, 48, 68, 67, 49, 48, 52, 67, 48}
    result := crypt.GetDefaultPassByte()
    if(!bytes.Equal(ok, result)) {
        t.Error("crypt.GetDefaultPassByte failed ok:", ok, "vs result:", result)
    }
}

func TestGetKey(t *testing.T) {
    ok := []byte {200, 144, 191, 9, 93, 72, 42, 233}
    result := crypt.GetKey(crypt.GetDefaultPass())
    if(!bytes.Equal(ok, result)) {
        t.Error("crypt.GetKey failed ok:", ok, "vs result:", result)
    }
}


Skip Tavakkolian

unread,
Oct 11, 2015, 5:06:23 AM10/11/15
to tuanhoanganh, golang-nuts
i'm guessing iteration and/or hash function doesn't match.  however, i'm not an expert; hopefully someone with first hand experience with pbkdf1 will comment.

if this is for a real application (rather than an exercise), PBKDF1 shouldn't be used. C#/.NET supports PBKDF2 (Rfc2898DeriveBytes).

tuanhoanganh

unread,
Oct 11, 2015, 8:42:40 AM10/11/15
to Skip Tavakkolian, golang-nuts
@Skip Tavakkolian
At first, thanks for your help. 

On C# at function Decrypt (..) value of algorithm.Key = {200, 144, 191, 9, 93, 72, 42, 233} so I will use this key in Go

Here is my function
=== crypt.go ====
.....
func DecryptString(encryptStr string, key string) string {
    data, err := base64.StdEncoding.DecodeString(encryptStr)
    if err != nil {
        panic(err)
    }
    return DecryptByte(data, key)
}

func DecryptByte(encryptByte []byte, key string) string {
    
    c, err := des.NewCipher([]byte {200, 144, 191, 9, 93, 72, 42, 233}) //des.NewCipher(GetKey(key))
    if err != nil {
        panic(err)
    }
    stream := cipher.NewCFBDecrypter(c, defaultIV)
    // XORKeyStream can work in-place if the two arguments are the same.
    stream.XORKeyStream(encryptByte, encryptByte)
    return fmt.Sprintf("%s", encryptByte)
}

=== crypt_test.go ===
...
func TestDecryptString(t *testing.T) {
    ok:= "admin123"
    result := crypt.DecryptString("W1ajloISkm7aVgxpnoqDvvGdGT44f3ub", "")
    if(result != ok)     {
        t.Error("DecryptString failed ok:", ok, " vs result: ", result);
    }
}

=== result of test ====

crypt_test.go:39: DecryptString failed ok: admin123 vs result: s�!h�˫f[�b? ��% ^


I am newbie of golang. Please help me.


Thanks in advance

wangxi...@gmail.com

unread,
Mar 20, 2016, 11:53:19 PM3/20/16
to golang-nuts
Have you figure out how to implement this?

Seem C# also need IV and Key to generate a key.

在 2015年10月4日星期日 UTC+8上午1:38:18,Tuan Hoang Anh写道:

kanaka...@gmail.com

unread,
Dec 29, 2018, 11:02:35 PM12/29/18
to golang-nuts
What algorithm using Rfc2898DeriveBytes

Pat Farrell

unread,
Jan 2, 2019, 12:35:42 AM1/2/19
to golang-nuts
On Saturday, October 3, 2015 at 1:38:18 PM UTC-4, Tuan Hoang Anh wrote:
Hello. How to inplement C# DESCryptoServiceProvider in Go Lang? I have Decrypt in C# and want Encrypt in go lang.

Can I ask a fundamental question: 
Why is anyone in 2019 trying to implement DES?

While it was made a standard in 15 January 1977 as FIPS PUB 46, it has been obsolete for all of this century. It was replaced by AES in 2002

Do not use DES for anything, not even protecting things from your baby sister. Use a real, modern strong cipher.
Reply all
Reply to author
Forward
0 new messages