none
如何用VB.NET達到這樣的JAVA DES加密 RRS feed

  • 問題

  • 我的環境是VS.NET 2003 And .NET 1.1
    如果可以用.NET 2.0做出來也沒差
    反正只要有辦法移值到.NET平台, 其他就小事了
     
    請大家幫幫忙
    公司幫客戶做異質平台整合
    為配合客戶原本的系統
    需要做到JAVA的加密程式

    以下為跟客戶要來的JAVA Source Code

    我要做的事情是
    把需要的字串利用底下Class的encode函數加密處理

    感謝幫忙

    import java.security.Key;
    import java.security.spec.KeySpec;

    import javax.crypto.Cipher;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.DESKeySpec;
    import javax.crypto.spec.IvParameterSpec;

    import org.apache.commons.beanutils.BeanUtils;
    import org.apache.commons.codec.binary.Base64;

    public class SecurityURL {
    private static String privatekey = "!s#$aJ_h&Cys@lI";
    private static String splitkey = "W&&#!A";
    private static SecretKeyFactory desFactory;
    private static KeySpec spec;
    private static Key deskey;

    static {
    try {
    // Generator the des key
    desFactory = SecretKeyFactory.getInstance("DES");
    spec = new DESKeySpec(privatekey.getBytes());
    deskey = desFactory.generateSecret(spec);


    } catch (Exception e) {
    e.printStackTrace();
    }
    }


    public static String encode(String url) throws Exception{

    // do encrypt the url
    Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
    c.init(Cipher.ENCRYPT_MODE, deskey);

    byte input[] = url.getBytes();
    byte encrypted[] = c.doFinal(input);
    byte iv[] = c.getIV();

    StringBuffer sb = new StringBuffer();
    sb.append(new String(Base64.encodeBase64Chunked(encrypted)));
    sb.append(splitkey);
    sb.append(new String(Base64.encodeBase64Chunked(iv)));

    return Base64URL.encode(sb.toString());
    }
    }

    <客戶給的Sample>
    原字串:
    taskID=Tsk000000082877&userName=Administrator&checkpass=false

    經過加密的字串:
    SmVLSTFHdEN5QlN5RlVWVkJHaTBRWDdrWDNtVEZma3R1eTlvSUhxQUQ3elpWNFZQdVd6VXZhSHNa%0D%0AWmlXWmpaRFlVRzhzU01ESjdiNw0KRUs2Sm9icDlrNWhhZnNSbzVnYzF0SzZ0NDMrNEZTMnNhSG5L%0D%
    0Ac1kxOGNWdjFVdDBXQ1QzRQ0KVyYkIyFBNWw4U1gzemN0dmM9DQo%3D%0D%0A

    其中的%0D、%0A應該是他有再經過類似.NET的Server.UrlEncode處理過
    所以如果只有這幾個地方不吻合應該就沒有錯了
    2006年11月22日 下午 06:53

解答

  • 你可以參考這個說明,  裡面有DES的實例

    http://www.microsoft.com/taiwan/msdn/secmod/html/secmod24.mspx

    2006年11月22日 下午 08:48
  • 我自己用的原始碼:

    DES: http://tlcheng.twbbs.org/TLCheng/Net/NetList.aspx?Action=Module&Module=33

    Base64: http://tlcheng.twbbs.org/TLCheng/Net/NetList.aspx?Action=Module&Module=6

    他那個 c.getIV 你也要弄到,不然沒有初始向量、Key 的產生方法時,也是沒輒。

    他看得出來是用 DES 加密 Bytes 後,再用 Base64 編碼,再用 Server.UrlEncode 編碼,解碼時,Server.UrlDecode ASP.NET 會自動做,所以就是用 Base64 解回 Bytes 再用 Key 跟 IV 解出 DES Bytes ,但是要轉何型態,就要看你原始變數型態了。

    2006年11月23日 上午 12:46
    版主
  • Hi,

    這麼久了,不曉得原PO您解決了沒。
    剛好最近我也需要整合類似的專案,故上網來搜尋,找到了您這篇!
    我想您的客戶所要整合的系統應該是Agentflow 2.x吧 Smile
    因為您提供的java source code,才得以讓我順利解決我的問題,所以也上來跟您報告一下解決的方法!
    原系統對於該編碼後的字串的處理方式應為(我推測的)
    1.先對該key值(即key=ooxx的ooxx)做Base64的反解
    2.再依splitkey分成兩個字串
    3.第二個字串即Initial Vector,private key他們一定有,所以即可用來解碼第一個字串
    4.所以就可以得出TskID, UserName, CheckPass等所需要的值
    我之前也一直不成功,一度想放棄,後來突然靈機一動,想說將已編碼後的字串反解回去看看是否可以得到原始字串
    在過程中才發現他的splitkey是錯的,因此也就順利解決了。
    順便附上我的原始碼,若您還沒解決,希望對您有所幫助!

    yaowf

     

    Code Snippet
     Public Class SecurityURL  
         '.Net中的privatekey好像只用8碼,所以把後面的去掉  
         '    Private Shared privatekey As String = "!s#$aJ_h&Cys@lI"  
         Private Shared privatekey As String = "!s#$aJ_h" 
         Private Shared splitkey As String = "W&$#!A"    '注意,原PO中的splitkey不對  
         Private Shared sIV As String = "[B@1efb8"   '此值隨便給即可,長度需為8個Bytes,此值是由原java程式中c.getIV()所得出,但每次都會不一樣,不過後來發現不一樣沒關係,因為這個值會接在splitkey後面傳給Agentflow  
         Public Shared Function encode(ByVal url As String) As String 
             Dim des As New DESCryptoServiceProvider()  
             Dim iba As Byte() = System.Text.Encoding.Default.GetBytes(url)  
             des.Padding = PaddingMode.PKCS7  
             des.Mode = CipherMode.CBC  
             des.Key = System.Text.Encoding.Default.GetBytes(privatekey)  
             des.IV = System.Text.Encoding.Default.GetBytes(sIV)  
             Dim ms As New MemoryStream  
             Dim cs As New CryptoStream(ms, des.CreateEncryptor, CryptoStreamMode.Write)  
             cs.Write(iba, 0, iba.Length)  
             cs.FlushFinalBlock()  
             Dim rt1 As String = Convert.ToBase64String(ms.ToArray)  
             Dim rt2 As String = Convert.ToBase64String(des.IV)  
             Return Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(rt1 + splitkey + rt2))  
         End Function 
     End Class 

     

    2007年4月9日 上午 10:58
  • 一定會不一樣的,就算您用客戶提供給您的Java source code去編譯後來執行也是不會一樣的!

    可是還是可以運作的,因為該編碼後的字串,先做Base64的反解會得到

    taskID=Tsk000000082877&userName=Administrator&checkpass=false 的DES加密值再轉Base64的字串及 IV 轉Base64的字串,

    而中間就是用splitkey去隔開的,所以,原系統(Agentflow)得到了 IV 後,自然就可以用原先的privatekey來解出

    taskID=Tsk000000082877&userName=Administrator&checkpass=false(先反轉Base64,再做DES解密)。

     

    每次加密出來的值不需要一樣,因為只要有IV就可以解出所需要的值。

    若真的要加密出一樣的結果的話,除非你可以拿到當初執行Security.encode時所產生的c.getIV()的值

    不然是沒辦法的。c.getIV()就我查的結果,只是隨機得出一組Initial Vector加密用而已!

    以上,供您參考!

     

    2007年4月10日 上午 11:41

所有回覆

  • 你可以參考這個說明,  裡面有DES的實例

    http://www.microsoft.com/taiwan/msdn/secmod/html/secmod24.mspx

    2006年11月22日 下午 08:48
  • 我自己用的原始碼:

    DES: http://tlcheng.twbbs.org/TLCheng/Net/NetList.aspx?Action=Module&Module=33

    Base64: http://tlcheng.twbbs.org/TLCheng/Net/NetList.aspx?Action=Module&Module=6

    他那個 c.getIV 你也要弄到,不然沒有初始向量、Key 的產生方法時,也是沒輒。

    他看得出來是用 DES 加密 Bytes 後,再用 Base64 編碼,再用 Server.UrlEncode 編碼,解碼時,Server.UrlDecode ASP.NET 會自動做,所以就是用 Base64 解回 Bytes 再用 Key 跟 IV 解出 DES Bytes ,但是要轉何型態,就要看你原始變數型態了。

    2006年11月23日 上午 12:46
    版主
  •  璉璉 寫信:

    我自己用的原始碼:

    DES: http://tlcheng.twbbs.org/TLCheng/Net/NetList.aspx?Action=Module&Module=33

    Base64: http://tlcheng.twbbs.org/TLCheng/Net/NetList.aspx?Action=Module&Module=6

    他那個 c.getIV 你也要弄到,不然沒有初始向量、Key 的產生方法時,也是沒輒。

    他看得出來是用 DES 加密 Bytes 後,再用 Base64 編碼,再用 Server.UrlEncode 編碼,解碼時,Server.UrlDecode ASP.NET 會自動做,所以就是用 Base64 解回 Bytes 再用 Key 跟 IV 解出 DES Bytes ,但是要轉何型態,就要看你原始變數型態了。

    璉大

    他程式就byte[] iv = c.getIV這樣而已

    沒有類似像byte[] iv = new byte[]{ (byte)0x8E, 0x12, 0x39, (byte)0x9C,0x07, 0x72, 0x6F, 0x5A};

    去指定他的初始向量

    不知道這樣他會帶什麼預設值給他嗎?

    至於他deskey的部份我應該要如何用.NET來做呢?

    感謝回覆
     

    2006年11月23日 上午 03:35
  • 我自己是用特定的方法產生 Key 跟 IV ,採用有規則的動態變化,增加破密的難度,所以你要問怎樣來的,每個人產生的方法都不同。

    不然就是把 Key 跟 IV 的 Byte 陣列內容抄出來。

    2006年11月23日 上午 06:13
    版主
  • Hi,

    這麼久了,不曉得原PO您解決了沒。
    剛好最近我也需要整合類似的專案,故上網來搜尋,找到了您這篇!
    我想您的客戶所要整合的系統應該是Agentflow 2.x吧 Smile
    因為您提供的java source code,才得以讓我順利解決我的問題,所以也上來跟您報告一下解決的方法!
    原系統對於該編碼後的字串的處理方式應為(我推測的)
    1.先對該key值(即key=ooxx的ooxx)做Base64的反解
    2.再依splitkey分成兩個字串
    3.第二個字串即Initial Vector,private key他們一定有,所以即可用來解碼第一個字串
    4.所以就可以得出TskID, UserName, CheckPass等所需要的值
    我之前也一直不成功,一度想放棄,後來突然靈機一動,想說將已編碼後的字串反解回去看看是否可以得到原始字串
    在過程中才發現他的splitkey是錯的,因此也就順利解決了。
    順便附上我的原始碼,若您還沒解決,希望對您有所幫助!

    yaowf

     

    Code Snippet
     Public Class SecurityURL  
         '.Net中的privatekey好像只用8碼,所以把後面的去掉  
         '    Private Shared privatekey As String = "!s#$aJ_h&Cys@lI"  
         Private Shared privatekey As String = "!s#$aJ_h" 
         Private Shared splitkey As String = "W&$#!A"    '注意,原PO中的splitkey不對  
         Private Shared sIV As String = "[B@1efb8"   '此值隨便給即可,長度需為8個Bytes,此值是由原java程式中c.getIV()所得出,但每次都會不一樣,不過後來發現不一樣沒關係,因為這個值會接在splitkey後面傳給Agentflow  
         Public Shared Function encode(ByVal url As String) As String 
             Dim des As New DESCryptoServiceProvider()  
             Dim iba As Byte() = System.Text.Encoding.Default.GetBytes(url)  
             des.Padding = PaddingMode.PKCS7  
             des.Mode = CipherMode.CBC  
             des.Key = System.Text.Encoding.Default.GetBytes(privatekey)  
             des.IV = System.Text.Encoding.Default.GetBytes(sIV)  
             Dim ms As New MemoryStream  
             Dim cs As New CryptoStream(ms, des.CreateEncryptor, CryptoStreamMode.Write)  
             cs.Write(iba, 0, iba.Length)  
             cs.FlushFinalBlock()  
             Dim rt1 As String = Convert.ToBase64String(ms.ToArray)  
             Dim rt2 As String = Convert.ToBase64String(des.IV)  
             Return Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(rt1 + splitkey + rt2))  
         End Function 
     End Class 

     

    2007年4月9日 上午 10:58
  • Hi 你好

    後來我還是沒有寫出來

    很高興這個Source Code對你有幫助

     

    最後是請對方協助

    寫一個WebService給我呼叫

    才解決這個問題

    2007年4月9日 下午 12:38
  • Hi 你好

    我照你的程式將

    taskID=Tsk000000082877&userName=Administrator&checkpass=false

    輸入

     

    得到的結果是

    dTVWU2FpRFQ5amtIclBsNXJWTHdFdjZYSVhDUG5EZHVGSlNoZVRRWWZFNWtr

    S1dVY3NJRGUxQklTUG96b3M3WjhnYzZ6RWtOUS93cUtJWDVpWkcxc2c9PVcmJC

    MhQVcwSkFNV1ZtWWpnPQ==

     

    似乎跟我一開始所提供的Sample不一樣

    不知道你是有改過什麼地方嗎

     

    感謝

    2007年4月9日 下午 01:37
  • 你原先就沒有 Key 跟 IV 的產生規則,怎麼可能解的出來...

     

    有規則的話,原先給你的範例就能解了...

    2007年4月9日 下午 02:07
    版主
  • 一定會不一樣的,就算您用客戶提供給您的Java source code去編譯後來執行也是不會一樣的!

    可是還是可以運作的,因為該編碼後的字串,先做Base64的反解會得到

    taskID=Tsk000000082877&userName=Administrator&checkpass=false 的DES加密值再轉Base64的字串及 IV 轉Base64的字串,

    而中間就是用splitkey去隔開的,所以,原系統(Agentflow)得到了 IV 後,自然就可以用原先的privatekey來解出

    taskID=Tsk000000082877&userName=Administrator&checkpass=false(先反轉Base64,再做DES解密)。

     

    每次加密出來的值不需要一樣,因為只要有IV就可以解出所需要的值。

    若真的要加密出一樣的結果的話,除非你可以拿到當初執行Security.encode時所產生的c.getIV()的值

    不然是沒辦法的。c.getIV()就我查的結果,只是隨機得出一組Initial Vector加密用而已!

    以上,供您參考!

     

    2007年4月10日 上午 11:41
  • 非常感謝

    這樣我知道了

     

    我一直以為c.getIV()每次的值會是一樣的

     

     

    2007年4月13日 上午 02:53