2015-10-18 73 views
0

我有解密用3DES加密字符串下面的代碼片段:解密密文TripleDes的靜態密鑰和IV通過的OpenSSL工具

private static byte[] KEY_192 = new byte[] 
{ 
    37, 19, 88, 164, 71, 3, 227, 30, 19, 
    174, 45, 84, 23, 253, 149, 108, 12, 
    107, 16, 192, 98, 22, 179, 200 
}; 

private static byte[] IV_192 = new byte[] 
{ 
    47, 108, 239, 71, 33, 98, 177, 13, 
    36, 51, 69, 88, 189, 17, 210, 14, 
    174, 230, 20, 60, 174, 100, 12, 22 
}; 

public static string DecryptTripleDES(string value) 
{ 
    if (!string.IsNullOrEmpty(value)) 
    { 
     System.Security.Cryptography.TripleDESCryptoServiceProvider cryptoProvider = new System.Security.Cryptography.TripleDESCryptoServiceProvider(); 
     byte[] buffer = System.Convert.FromBase64String(value); 
     System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer); 
     System.Security.Cryptography.CryptoStream cs = new System.Security.Cryptography.CryptoStream(ms, cryptoProvider.CreateDecryptor(DataEncryptionEngine.KEY_192, DataEncryptionEngine.IV_192), System.Security.Cryptography.CryptoStreamMode.Read); 
     System.IO.StreamReader sr = new System.IO.StreamReader(cs); 
     return sr.ReadToEnd(); 
    } 
    return null; 
} 

我試圖使用OpenSSL或Ruby,但沒有複製它運氣,加密base64編碼字符串的一個例子是:

JDiLOoP3iIY= 

當在Linux下嘗試此操作時出現以下錯誤。

$ echo JDiLOoP3iIY = | openssl enc -d -des3 -a -K 371988164713227301917445842325314910812107161929822179200 -iv 471082397133981771336516988189172101417423020601741001222;十六進制字符串 太長無效十六進制值

我錯過了什麼?謝謝!

編輯:如果有幫助,這是加密的字符串函數:

public static string EncryptTripleDES(string value) 
{ 
    if (!string.IsNullOrEmpty(value)) 
    { 
     System.Security.Cryptography.TripleDESCryptoServiceProvider cryptoProvider = new System.Security.Cryptography.TripleDESCryptoServiceProvider(); 
     System.IO.MemoryStream ms = new System.IO.MemoryStream(); 
     System.Security.Cryptography.CryptoStream cs = new System.Security.Cryptography.CryptoStream(ms, cryptoProvider.CreateEncryptor(DataEncryptionEngine.KEY_192, DataEncryptionEngine.IV_192), System.Security.Cryptography.CryptoStreamMode.Write); 
     System.IO.StreamWriter sw = new System.IO.StreamWriter(cs); 
     sw.Write(value); 
     sw.Flush(); 
     cs.FlushFinalBlock(); 
     ms.Flush(); 
     return System.Convert.ToBase64String(ms.GetBuffer(), 0, System.Convert.ToInt32(ms.Length)); 
    } 
    return null; 
} 

想這對紅寶石也一樣,我得到 '壞解密'

#!/usr/bin/env ruby 

require 'openssl' 
require 'base64' 

string = 'JDiLOoP3iIY=' 

def decrypt(cpass) 
    cipher = OpenSSL::Cipher::Cipher.new("des-ede-cbc") 
    cipher.decrypt 
    cipher.key = "251358A44703E31E13AE2D5417FD956C0C6B10C06216B3C8" 
    cipher.iv = "2F6CEF472162B10D24334558BD11D20EAEE6143CAE640C16" 
    return cipher.update(Base64.decode64(cpass)) + cipher.final 
end 

decrypted = decrypt(string) 

puts "decrypted string: #{decrypted}" 
+0

3DES需要64位的IV,不192位的IV。 – CodesInChaos

+0

我知道,但這是怎麼在這個代碼中使用... – bsteo

回答

2
  1. IV大小需要匹配塊大小,而不是密鑰大小。所以3DES需要64位IV,而不是192位IV。

    我猜你現有的代碼只是忽略了前64位以外的所有內容。嘗試在rubu/OpenSSL中將其截斷爲64位(16個十六進制字符)。

  2. 您沒有正確地將它們轉換爲十六進制。 C#中的值是十進制的,不能簡單地連接它們以形成十六進制字符串。

    轉換爲十六進制我越來越:

    Key = 25-13-58-A4-47-03-E3-1E-13-AE-2D-54-17-FD-95-6C-0C-6B-10-C0-62-16-B3-C8 
    IV = 2F-6C-EF-47-21-62-B1-0D-24-33-45-58-BD-11-D2-0E-AE-E6-14-3C-AE-64-0C-16 
    

    所以我想你需要使用

    Key = 251358A44703E31E13AE2D5417FD956C0C6B10C06216B3C8 
    IV = 2F6CEF472162B10D 
    
  3. C#的輸出Base64編碼。我在你的ruby代碼中沒有看到任何與Base64相關的東西。

  4. 我不知道ruby的默認填充是什麼,但是對於C#,它是PKCS#5/PKCS#7填充(這些是同一事物的兩個名稱)。

這是不安全的。使用靜態IV會忽略IV的要點,每個消息應該有所不同。它沒有MAC,所以它遭受主動攻擊,包括填充神諭。最後,64位分組密碼不應使用單個密鑰對幾個GB進行加密。

+0

試圖連接我得到壞解密:'echo JDiLOoP3iIY = | openssl enc -d -des3 -a -K 251358A44703E31E13AE2D5417FD956C -iv 2F6CEF472162B10D24334558BD11D20E;' – bsteo

+0

@bsteo我不熟悉openssl工具。也許它是一個不同的填充。 C#默認使用PKCS#5/PKCS#7填充。你的IV太長,你的鑰匙太短。 – CodesInChaos

+0

是的,當我通過互聯網閱讀時,C#'TripleDESCryptoServiceProvider'和其他「工具」(如OpenSSL或PHP的mcrypt)之間存在一些不兼容問題。 – bsteo

0

感謝CodesInChaos,我解決了我的問題。

  1. 的OpenSSL:

    echo JDiLOoP3iIY= | openssl enc -d -des3 -a -K 251358A44703E31E13AE2D5417FD956C0C6B10C06216B3C8 -iv 2F6CEF472162B10D; 
    

輸出:

  • 紅寶石:

    require 'openssl' 
    require 'base64' 
    
    string = 'JDiLOoP3iIY=' 
    
    def decrypt(cpass) 
        cipher = OpenSSL::Cipher::Cipher.new("des3") 
        cipher.decrypt 
        cipher.key = "37,19,88,164,71,3,227,30,19,174,45,84,23,253,149,108,12,107,16,192,98,22,179,200".split(',').map { |x| x.to_i }.pack('c*') 
        cipher.iv = "47,108,239,71,33,98,177,13".split(',').map { |x| x.to_i }.pack('c*') 
        return cipher.update(Base64.decode64(cpass)) + cipher.final 
    end 
    
    decrypted = decrypt(string) 
    
    puts "decrypted string: #{decrypted}" 
    
  • 輸出:

    解密的字符串:792