2016-11-08 28 views
3

我試圖解密使用pgcrypto加密的數據。我沒有使用IV,因爲它只是一個測試,但我無法用C#解密數據。解密通過pgcrypto加密的數據(使用C#)

加密在POSTGRES:

enc_key := '\\xAACE38F289EC3EA209B48D'; 

-- Time insertions 
ts_start := clock_timestamp(); 
FOR i IN 1..num_loops LOOP 

    -- The text to insert and its key 
    plaintext := 'Number: ' || i; 
    plaintext_pk := gen_random_uuid(); 
    plaintext_pk_as_text := plaintext_pk::text; 

    -- The ref entries 
    user_pk := gen_random_uuid(); 
    user_ref_pk := encrypt(plaintext_pk_as_text::bytea, enc_key, 'aes'); 

    -- Add the enries 
    INSERT INTO "Text" VALUES(plaintext_pk, plaintext); 
    INSERT INTO "User" VALUES(user_ref_pk, user_pk); 

END LOOP; 
ts_end := clock_timestamp(); 
elapsed_raw := cast(extract(epoch from (ts_end - ts_start)) as numeric(18,3)); 

解密在C#:

// The decryption key 
byte[] enc_key = new byte[] { 0xAA, 0xCE, 0x38, 0xF2, 0x89, 0xEC, 0x3E, 0xA2, 0x09, 0xB4, 0x8D, 
0x00, 0x00, 0x00, 0x00, 0x00 }; 

public static string AESDecryptByteArray(byte [] encoded_data, byte [] key) 
{ 
    string result = ""; 
    byte [] result_ba = new byte[64]; 

    using (Aes myAes = Aes.Create()) 
    { 
     if (myAes == null) 
     { 
      throw new Exception("Failed to create AES object."); 
     } 

     myAes.Key = key; 
     myAes.Mode = CipherMode.CBC; 
     myAes.Padding = PaddingMode.PKCS7; 

     MemoryStream streamMem = new MemoryStream(encoded_data); 

     byte[] IV = new byte[16]; 
     // streamMem.Read(IV, 0, 16); 
     for (int i = 0; i < 16; ++i) 
     { 
      IV[i] = 0; 
     } 
     myAes.IV = IV; 

     int iNumBytes = 0; 
     var decryptor = myAes.CreateDecryptor(); 
     using (CryptoStream streamCrypt = new CryptoStream(streamMem, decryptor, CryptoStreamMode.Read)) 
     { 
      iNumBytes = streamCrypt.Read(result_ba, 0, 48); 
     } 

     result = System.Text.Encoding.ASCII.GetString(result_ba); 
    } 

    return result; 

} // AESDecryptByteArray 

我從行之一,並且二進制密鑰複製的產生的加密數據,但C#代碼保持與吹CryptographicException(「填充無效且無法移除」)異常。我的理解是,pgcrypto的encrypt()默認爲cbc \ pkcs。很明顯,我錯過了一些東西。

任何幫助感激地收到。

亞當。

+0

也許你可以嘗試使用C#函數對數據進行加密,並嘗試使加密數據與PostGres數據匹配100%。一旦匹配,您應該能夠找到兩個系統之間的斷開連接。 –

+0

謝謝,邁克爾 - 很好的建議。我會試試看。或者甚至確保我只能在C#中進行加密和解密才能開始。 –

回答

3

嘗試了邁克爾的建議,並沒有得到正確的結果,當然。發現問題。 PG的字符串到bytea的轉換不是不小心的。重要線索來自

DO $$ 

    declare enc_data bytea; 
     enc_key  bytea; 

     dec_bytea bytea; 
     dec_text text; 

begin 

    enc_data := '\305\347fyau\030 \223\014E\307\346\267|\365R\3236l\322f\344\312z\220\271\207C\003\255\210+\316\330&\205l>\342\203\350\214$W\253\370D'; 
    enc_key := '\\xAACE38F289EC3EA209B48D'; 

    dec_bytea := decrypt(enc_data, enc_key, 'aes'); 
    dec_text := dec_bytea::text; 

    raise info 'Decoded text -> %', dec_text; 

    DROP TABLE IF EXISTS tmpTable; 
    CREATE TEMPORARY TABLE tmpTable AS 
     select dec_text as "Decoded text", 
      char_length(dec_text) as "Decoded length", 
      length(enc_data) as "Encoded length", 
      enc_key as "Enc Key", 
      length(enc_key) as "Enc Key Len", 
      encode(enc_key, 'hex') as "Hex key", 
      encode(enc_key, 'escape') as "Esc key"; 

END $$; 

select * from tmpTable; 

這表明PG中的二進制密鑰是24個字節長 - 而不是我所期望的。 這是誤解我的一部分,如何PG的字符串到字節轉換的作品。我認爲「\\ xAACE38F289EC3EA209B48D」會轉換成一個11字節的數組(https://www.postgresql.org/docs/9.6/static/datatype-binary.html,第8.4.1節),但不需要雙倍的反斜槓。 所以我的字符串轉換爲'\','x','A'...'D' - 一個24字節的數組。

// 
// In C# this is the key needed 
// 
byte[] enc_key_aaaahhhh = 
new byte[] { 0x5c, 0x78, 0x41, 0x41, 0x43, 0x45, 0x33, 0x38, 
       0x46, 0x32, 0x38, 0x39, 0x45, 0x43, 0x33, 0x45, 
       0x41, 0x32, 0x30, 0x39, 0x42, 0x34, 0x38, 0x44 }; 

// 
// This is wrong. 
// For this key you'd need to enter '\xAACE38F289EC3EA209B48D' in PG - only one backslash 
// 
byte[] enc_key = new byte[] { 0xAA, 0xCE, 0x38, 0xF2, 0x89, 0xEC, 0x3E, 0xA2, 0x09, 0xB4, 0x8D, 
           0x00, 0x00, 0x00, 0x00, 0x00 }; 

(並沒有幫助,我抄錯GUID到我的C#代碼進行比較的 - 真正的GUID是「d6edd775-47c5-4779-a761-7f8297130073」)

希望這也許有一天幫助別人。

  • Adam。
+0

不錯,謝謝 – lhk

+0

很高興你工作了:) –