2017-04-07 72 views
2

我需要在C#中對一個值進行加密,然後在經典ASP中對其進行解密。我最接近的是Blowfish。但問題是這兩個實現產生稍微不同的結果,我不知道爲什麼。Blowfish在C#和經典ASP之間的結果不同

實現使用:

C#:https://defuse.ca/blowfish.htm

的VBScript:http://www.di-mgt.com.au/cryptoBlowfishASP.html

C#代碼:

var input = "Hello World"; 
var key = "04B915BA43FEB5B6"; 
BlowFish b = new BlowFish(key); 

string enc, dec; 

enc = b.Encrypt_ECB(input); 
dec = b.Decrypt_ECB(enc); 

的VBScript:

Dim aKey() 
Dim nKeyLen, szTxtKey, szTxtPlain, szTxtKeyAsString, szTxtCipher, szTxtCipherHex, szTxtCipher64, szTxtDecrypt 

szTxtKey = "04B915BA43FEB5B6" 
szTxtPlain = "Hello World" 

ReDim aKey((Len(szTxtKey) \ 2) - 1) 
nKeyLen = bu_HexStr2Bytes(szTxtKey, aKey) 
Call blf_Key(aKey, nKeyLen) 
szTxtKeyAsString = bu_Bytes2HexStr(aKey, nKeyLen) 

szTxtCipher = blf_StringEnc(szTxtPlain) 
szTxtCipherHex = bu_Str2Hex(szTxtCipher) 

C#輸出:

819dd50a925a5eb83ed723bea6d84984 

VBScript的輸出:

819DD50A925A5EB8CABE974A654A18A8 

輸出的前半部分是相同的: 「819DD50A925A5EB8」

一個有趣的事情是,如果我解密的VBScript輸出與C#庫我得到這個: Hello World♣♣♣♣♣

所以...它幾乎可以工作,但有某種填充或發生的事情。我不知道如何解決這個問題。

+2

不同的填充:https://en.wikipedia.org/wiki/Padding_(cryptography) –

+0

@ArtjomB。這就是我在想什麼,所以這意味着這兩個實現是不兼容的,沒有辦法讓他們一起工作而不重寫/改變其中的一個? – FirstDivision

+0

在最糟糕的情況下,可以在代碼中解決填充問題。但是,不要使用Blowfish,它已經過時了,即使它的作者現在使用AES。 AES不僅比Blowfish更難使用,而且更安全。 – zaph

回答

2

由於@artjom-balready mentioned in the comments,罪魁禍首是不同的填充。

對不同的填充方法here有很好的解釋。

分析blowfish.cs文件顯示它使用NULL填充(請注意此文件中的片段);

/// <summary> 
/// Decrypts a string (ECB) 
/// </summary> 
/// <param name="ct">hHex string of the ciphertext</param> 
/// <returns>Plaintext ascii string</returns> 
public string Decrypt_ECB(string ct) 
{ 
    return Encoding.ASCII.GetString(Decrypt_ECB(HexToByte(ct))).Replace("\0", ""); 
} 

與此相反,傳統的ASP實現使用PKCS5填充(從basBlowfishFns.asp片斷顯示PKCS5方法)

Using Padding in Encryption
墊與字節所有相同的值的數量的填充字節(PKCS5填充)

' Get # of padding bytes from last char 
nPad = Asc(Right(strData, 1)) 
If nPad > 8 Then nPad = 0 ' In case invalid 
strData = Left(strData, nLen - nPad) 

此修復措施是爲c#庫使用的NULL填充應用變通方法。

這裏是修改的basBlowfishFns.asp(只是顯示修改後的功能);

Public Function blf_StringEnc(strData, padMethod) 
' Encrypts plaintext strData after adding RFC 2630 padding 
' Returns encrypted string. 
' Requires key and boxes to be already set up. 
' Version 5. Completely revised. 
' The speed improvement here is due to Robert Garofalo. 
    Dim strIn 
    Dim strOut 
    Dim nLen 
    Dim sPad 
    Dim nPad 
    Dim nBlocks 
    Dim i 
    Dim j 
    Dim aBytes(7) 
    Dim sBlock 
    Dim iIndex 

    ' Pad data string to multiple of 8 bytes 
    strIn = PadString(strData, padMethod) 
    ' Calc number of 8-byte blocks 
    nLen = Len(strIn) 
    nBlocks = nLen \ 8 
    ' Allocate output string here so we can use Mid($ below 
    ' strOut = String(nLen, " ") 
    strOut = ""  ' Fix for VBScript 

    ' Work through string in blocks of 8 bytes 
    iIndex = 0 
    For i = 1 To nBlocks 
     sBlock = Mid(strIn, iIndex + 1, 8) 
     ' Convert to bytes 
     ' aBytes() = StrConv(sBlock, vbFromUnicode) 
     Call bu_String2Bytes(sBlock, aBytes) 
     ' Encrypt the block 
     Call blf_EncryptBytes(aBytes) 
     ' Convert back to a string 
     ' sBlock = StrConv(aBytes(), vbUnicode) 
     sBlock = bu_Bytes2String(aBytes, 8) 
     ' Copy to output string 
     ' Mid(strOut, iIndex + 1, 8) = sBlock 
     strOut = strOut & sBlock 
     iIndex = iIndex + 8 
    Next 

    blf_StringEnc = strOut 

End Function 

Public Function blf_StringDec(strData, padMethod) 
' Decrypts ciphertext strData and removes RFC 2630 padding 
' Returns decrypted string. 
' Requires key and boxes to be already set up. 
' Version 5. Completely revised. 
' The speed improvement here is due to Robert Garofalo. 
    Dim strIn 
    Dim strOut 
    Dim nLen 
    Dim sPad 
    Dim nPad 
    Dim nBlocks 
    Dim i 
    Dim j 
    Dim aBytes(7) 
    Dim sBlock 
    Dim iIndex 

    strIn = strData 
    ' Calc number of 8-byte blocks 
    nLen = Len(strIn) 
    nBlocks = nLen \ 8 
    ' Allocate output string here so we can use Mid($ below 
    'strOut = String(nLen, " ") 
    strOut = "" 

    ' Work through string in blocks of 8 bytes 
    iIndex = 0 
    For i = 1 To nBlocks 
     sBlock = Mid(strIn, iIndex + 1, 8) 
     ' Convert to bytes 
     ' aBytes() = StrConv(sBlock, vbFromUnicode) 
     Call bu_String2Bytes(sBlock, aBytes) 
     ' Encrypt the block 
     Call blf_DecryptBytes(aBytes) 
     ' Convert back to a string 
     'sBlock = StrConv(aBytes(), vbUnicode) 
     sBlock = bu_Bytes2String(aBytes, 8) 
     ' Copy to output string 
     ' Mid(strOut, iIndex + 1, 8) = sBlock 
     strOut = strOut & sBlock 
     iIndex = iIndex + 8 
    Next 

    ' Strip padding, if valid 
    strOut = UnpadString(strOut, padMethod) 

    blf_StringDec = strOut 

End Function 

Public Function PadString(strData, method) 
' Pad data string to next multiple of 8 bytes as per RFC 2630 
    Dim nLen 
    Dim sPad 
    Dim nPad 
    nLen = Len(strData) 
    nPad = ((nLen \ 8) + 1) * 8 - nLen 
    Select Case method 
    Case "PKCS5" 
     sPad = String(nPad, Chr(nPad)) ' Pad with # of pads (1-8) 
    Case "NULL" 
     sPad = String(nPad, Chr(0)) ' Pad with # of NULL characters 
    End Select 
    PadString = strData & sPad 

End Function 

Public Function UnpadString(strData, method) 
' Strip RFC 2630-style padding 
    Dim nLen 
    Dim nPad 
    nLen = Len(strData) 
    If nLen = 0 Then Exit Function 
    Select Case method 
    Case "PKCS5" 
     ' Get # of padding bytes from last char 
     nPad = Asc(Right(strData, 1)) 
     If nPad > 8 Then nPad = 0 ' In case invalid 
     strData = Left(strData, nLen - nPad) 
    Case "NULL" 
     'Remove any NULL characters, obviously, this method isn't ideal if 
     'the data contains valid NULLs. This shouldn't be an issue with 
     'ASCII text. 
     strData = Replace(strData, Chr(0), "") 
    End Select 
    UnpadString = strData 
End Function 

重要的修改是對PadString()UnpadString()功能。我添加了一個參數method,允許您傳遞標識符NULLPKCS5以確定我們如何填充/取消填充數據。這些功能已經存在,但由於某種原因,blf_StringEnc()blf_StringDec()功能沒有使用,所以爲了DRY principle的利益,我修改了它們以便它們被使用。

使用以下代碼修改(這只是快速刺激代碼更靈活);

Dim aKey() 
Dim nKeyLen, szTxtKey, szTxtPlain, szTxtKeyAsString, szTxtCipher, szTxtCipherHex, szTxtCipher64, szTxtDecrypt 

szTxtKey = "04B915BA43FEB5B6" 
szTxtPlain = "Hello World" 

ReDim aKey((Len(szTxtKey) \ 2) - 1) 
nKeyLen = bu_HexStr2Bytes(szTxtKey, aKey) 
Call blf_Key(aKey, nKeyLen) 
szTxtKeyAsString = bu_Bytes2HexStr(aKey, nKeyLen) 

'Encrypt using NULL padding method. 
szTxtCipher = blf_StringEnc(szTxtPlain, "NULL") 
szTxtCipherHex = bu_Str2Hex(szTxtCipher) 

Call Response.Write(szTxtCipherHex) 

會導致;

819DD50A925A5EB83ED723BEA6D84984 

如原先預期。

+0

感謝您的優秀迴應,解釋和解決方案! – FirstDivision

2

如果您可以從VBScript轉出命令行,則可以使用加密字符串的相同C#庫創建控制檯應用程序。有點解決方法,但你會使用相同的庫。