2013-01-24 48 views
2

我对编码和密码学都很陌生,所以我问的问题可能太基本了。我需要加密提供给我的值,并将加密的值以及用于加密的IV存储在文档中。使用存储在别处的主密钥完成加密。我使用AES加密和加密的代码如下所示:将AES加密字节和IV存储到XML的最佳方法是什么?

private EncryptedData EncryptValue(string value, byte[] encryptedMasterKey) 
     { 
      byte[] encryptedValue = new byte[0]; 
      AesCryptoServiceProvider aesCryptoServiceProvider = null; 

      //decrypt the master key 
      encryptedMasterKey = DecryptMasterKey(encryptedMasterKey); 

      // Create an AesCryptoServiceProvider object 
      // with the specified key and IV.     
      using (aesCryptoServiceProvider = new AesCryptoServiceProvider()) 
      { 
       aesCryptoServiceProvider.Key = encryptedMasterKey; 

       // Create an encryptor to perform the stream transform. 
       ICryptoTransform encryptor = aesCryptoServiceProvider.CreateEncryptor(
        aesCryptoServiceProvider.Key, aesCryptoServiceProvider.IV); 

       // Create the streams used for encryption. 
       using (MemoryStream msEncrypt = new MemoryStream()) 
       { 
        using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 
        { 
         using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) 
         { 
          //Write all data to the stream. 
          swEncrypt.Write(value); 
         } 
         encryptedValue = msEncrypt.ToArray(); 
        } 
       } 
      } 

      EncryptedData encryptedData = new EncryptedData(encryptedValue, aesCryptoServiceProvider.IV); 
      return encryptedData; 
     } 

将数据写入到XML的代码如下所示:

public void WriteData(string id, EncryptedData encryptedData) 
    { 

     XDocument document = GetValidDocument(); 
     XElement[] encryptedDataElements = null; 
     XElement encryptedDataElement; 
     encryptedDataElements = (from element in document.Descendants(EncryptedDataElementName) 
           where element.Element(IdElementName).Value.ToUpper() == id.ToUpper() 
           select element).ToArray(); 
     if (encryptedDataElements.Count() != 0) 
     { 
      encryptedDataElement = encryptedDataElements.First(); 
      encryptedDataElement.Remove(); 
     } 
     encryptedDataElement = new XElement(EncryptedDataElementName); 
     XElement idElement = new XElement(IdElementName, id); 
     encryptedDataElement.Add(idElement); 
     XElement encryptedValueElement = new XElement(EncryptedValueElementName); 
     encryptedValueElement.SetValue(Encoding.UTF8.GetString(encryptedData.EncryptedValue)); 
     XElement saltElement = new XElement(SaltElementName, Encoding.UTF8.GetString(encryptedData.Salt)); 
     encryptedDataElement.Add(encryptedValueElement); 
     encryptedDataElement.Add(saltElement); 
     document.Element(StoreElementName).Add(encryptedDataElement); 
     IXmlService xmlService = GlueRegistry.Instance.GetService<IXmlService>(); 
     xmlService.SaveXmlDocument(document, filePath); 
    } 

我想,这可能是更好的为拯救一个UTF8编码的字符串并将值返回为UTF8编码的字节数组。随着数据逐个写入,序列化不是一种选择。问题出在Encoding.UTF8.GetString的SetValue方法中。我也明白,我应该使用XElement.Parse。我用这个,我得到一个例外,说这个值是无效的。我现在想知道UTF8是否是一个好选择,或者如果有另一种更好的方式来做我想做的事情。

在此先感谢您的帮助!

回答

3
  1. 对于编码,我推荐Base64。 Utf8旨在将文本转换为字节。它不能将任意的二进制数据转换为文本。
  2. 我建议使用经过身份验证的加密/添加MAC。未经身份验证的加密会引发主动攻击,如填充字符。

所以,你的代码变得像:

byte[] ciphertext = iv + Encrypt(key, m); 
byte[] ciphertextWithMAC = ciphertext + HMAC(key, ciphertext) 
string encodedCiphertext = Base64Encode(cipherText) 
+1

我非常同意使用经过身份验证的加密。没有它,许多攻击是可能的。 – usr

0

尽管我怀疑是否存储单个字节的加密, 要求蛮力攻击,但表示形式对我来说很明显:使用数据类型hexBinary(所以“ ABC“将会像”414243“一样)。这使加密值的长度加倍,但由于XML开销,这不太可能成为问题。优点是:不需要特殊的字符处理,清晰可见和有点可读。

+0

没有理由为什么一个加密的字节会更容易比多次攻击。 – CodesInChaos

+0

@CodesinChaos:只有256个不同的输入对我来说看起来更脆弱?! – guidot

+0

@guidot你怎么知道哪个输入是正确的?一般来说,拥有更多的明文/密文对安全性是有害的,因为还有更多要测试的东西。如果你的协议是精心设计的,那还是无关紧要的。 –

相关问题