2012-10-02 89 views
5

我想在Portable Class Library Contrib project on codeplex中使用加密,但还没有找到任何有关如何使用它的文档。便携式类库(PCL)贡献 - 加密

我想创建一个包装类,EncryptDecrypt里面的方法,我想这个包装类存在一个可移植的类库。本项目中我引用Portable.RuntimePortable.Security.Cryptography。它是否正确?

然后我想在.NET,Windows Phone和Metro项目中使用我的包装。在这些项目中,我参考了我的包装项目Portable.RuntimePortable.Security.Cryptography和相应的便携式项目,即Portable.Desktop,Portable.PhonePortable.WindowsStore。它是否正确?

但是,当我尝试使用包装类时,出现冲突的命名空间错误。这是错误,我的包装类:

类型System.Security.Cryptography.AesManaged两个C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client\System.Core.dllC:\Downloads\PclContrib\bin\Debug\Portable.Security.Cryptography.dll

public sealed class SymmetricCryptography<T> where T : SymmetricAlgorithm, new() 
{ 
    private readonly T provider = new T(); 
    private readonly UTF8Encoding utf8 = new UTF8Encoding(); 

    private byte[] key; 
    private byte[] iv; 

    public byte[] Key 
    { 
     get { return this.key; } 
    } 

    public byte[] IV 
    { 
     get { return this.iv; } 
    } 

    public SymmetricCryptography() 
    { 
     this.key = this.provider.Key; 
     this.iv = this.provider.IV; 
    } 

    public SymmetricCryptography(byte[] key, byte[] iv) 
    { 
     this.key = key; 
     this.iv = iv; 
    } 

    public SymmetricCryptography(string password, string salt) 
    { 
     Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(password, this.utf8.GetBytes(salt)); 
     this.key = deriveBytes.GetBytes(this.provider.KeySize >> 3); 
     this.iv = deriveBytes.GetBytes(16); 
    } 

    public SymmetricCryptography(string password, string salt, int iterations) 
    { 
     Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(password, this.utf8.GetBytes(salt), iterations); 
     this.key = deriveBytes.GetBytes(this.provider.KeySize >> 3); 
     this.iv = deriveBytes.GetBytes(16); 
    } 

    public byte[] Encrypt(byte[] input) 
    { 
     return this.Encrypt(input, this.key, this.iv); 
    } 

    public byte[] Encrypt(byte[] input, byte[] key, byte[] iv) 
    { 
     return this.Transform(
      input, 
      this.provider.CreateEncryptor(key, iv)); 
    } 

    public byte[] Decrypt(byte[] input) 
    { 
     return this.Decrypt(input, this.key, this.iv); 
    } 

    public byte[] Decrypt(byte[] input, byte[] key, byte[] iv) 
    { 
     return this.Transform(
      input, 
      this.provider.CreateDecryptor(key, iv)); 
    } 

    public string Encrypt(string text) 
    { 
     return this.Encrypt(text, this.key, this.iv); 
    } 

    public string Encrypt(string text, byte[] key, byte[] iv) 
    { 
     byte[] output = this.Transform(
      this.utf8.GetBytes(text), 
      this.provider.CreateEncryptor(key, iv)); 
     return Convert.ToBase64String(output); 
    } 

    public string Decrypt(string text) 
    { 
     return this.Decrypt(text, this.key, this.iv); 
    } 

    public string Decrypt(string text, byte[] key, byte[] iv) 
    { 
     byte[] output = this.Transform(
      Convert.FromBase64String(text), 
      this.provider.CreateDecryptor(key, iv)); 
     return this.utf8.GetString(output, 0, output.Length); 
    } 

    public void Encrypt(Stream input, Stream output) 
    { 
     this.Encrypt(input, output, this.key, this.iv); 
    } 

    public void Encrypt(Stream input, Stream output, byte[] key, byte[] iv) 
    { 
     this.TransformStream(true, ref input, ref output, key, iv); 
    } 

    public void Decrypt(Stream input, Stream output) 
    { 
     this.Decrypt(input, output, this.key, this.iv); 
    } 

    public void Decrypt(Stream input, Stream output, byte[] key, byte[] iv) 
    { 
     this.TransformStream(false, ref input, ref output, key, iv); 
    } 

    private byte[] Transform(
     byte[] input, 
     ICryptoTransform cryptoTransform) 
    { 
     byte[] result; 

     using (MemoryStream memoryStream = new MemoryStream()) 
     { 
      using (CryptoStream cryptStream = new CryptoStream(
       memoryStream, 
       cryptoTransform, 
       CryptoStreamMode.Write)) 
      { 
       cryptStream.Write(input, 0, input.Length); 
       cryptStream.FlushFinalBlock(); 
       memoryStream.Position = 0; 
       result = memoryStream.ToArray(); 
      } 
     } 

     return result; 
    } 

    private void TransformStream(bool encrypt, ref Stream input, ref Stream output, byte[] key, byte[] iv) 
    { 
     // defensive argument checking 
     if (input == null) 
     { 
      throw new ArgumentNullException("input"); 
     } 

     if (output == null) 
     { 
      throw new ArgumentNullException("output"); 
     } 

     if (!input.CanRead) 
     { 
      throw new ArgumentException("Unable to read from the input Stream.", "input"); 
     } 

     if (!output.CanWrite) 
     { 
      throw new ArgumentException("Unable to write to the output Stream.", "output"); 
     } 

     // make the buffer just large enough for 
     // the portion of the stream to be processed 
     byte[] inputBuffer = new byte[input.Length - input.Position]; 
     // read the stream into the buffer 
     input.Read(inputBuffer, 0, inputBuffer.Length); 
     // transform the buffer 
     byte[] outputBuffer = encrypt ? Encrypt(inputBuffer, key, iv) 
             : Decrypt(inputBuffer, key, iv); 
     // write the transformed buffer to our output stream 
     output.Write(outputBuffer, 0, outputBuffer.Length); 
    } 
} 
+1

如果你解决你的问题,发布的解决方案作为一个答案,而不是编辑成问题。或者还有其他问题吗?如果是这样,你应该明确地陈述它们。 – CodesInChaos

+1

btw你的IV使用是不好的。对于您执行的每种加密,IV应该不同。 – CodesInChaos

回答

1

事实证明,我对加密算法的通用包装是造成问题的存在。 PCL Contrib包含一个名为SymmetricAlgorithm的类,它本身就是真正的SymmetricAlgorithm的包装。如果我让我的包装类非通用它的工作原理是这样的:

public sealed class AesManagedSymmetricCryptography : SymmetricCryptography<AesManaged> 
{ 
    #region Constructors 

    public AesManagedSymmetricCryptography() 
    { 
    } 

    public AesManagedSymmetricCryptography(byte[] key, byte[] iv) 
     : base(key, iv) 
    { 
    } 

    public AesManagedSymmetricCryptography(string password, string salt) 
     : base(password, salt) 
    { 
    } 

    public AesManagedSymmetricCryptography(string password, string salt, int iterations) 
     : base(password, salt, iterations) 
    { 
    } 

    #endregion 
} 
+0

你还可以包含一个使用这个函数的几行代码的例子吗? –

+0

我也尝试使用pcl-contrib加密技术来提供windows phone 8和windows store应用程序。 所以,我没有从问题 和删除“密封”复制代码从它 '公共类SymmetricCryptography 其中T:SymmetricAlgorithm,新的()......' 这样我就可以创建它的非通用版本,像你建议的那样。 请问您可以在这里发布一个解决方案吗? –

+0

您已经使用过'this.provider.KeySize',但提供者是SymmetricAlgorithm,它没有KeySize? –

3

该文档是有点欠缺,但我在FAQ拨打了这一点:

我可以从共享类型PclContrib与我的平台特定的项目?不,目前不。虽然PclContrib look和 中的类型与其特定于平台的对应类似,但运行时和编译器会将它们视为完全不同的类型。虽然我们有 关于如何使这项工作的一些想法,但这是一个功能,我们不会 在短期内寻找。

2

以下.net代码适用于桌面实现。 首先引用添加Portable.Desktop和Portable.Security.Cryptography.ProtectedData

private void button2_Click(object sender, EventArgs e) 
    { 
     String encrypted = PCL.CentralClass.Encrypt("yo"); 
     String decreypted = PCL.CentralClass.Decrypt(encrypted); 
     //PCL.CentralClass. 
    } 
    //https://pclcontrib.codeplex.com/documentation?FocusElement=Comment 
    //\Source\Portable.Security.Cryptography.ProtectedData\Security\Cryptography\ProtectedData.cs 

    static byte[] GetBytes(string str) 
    { 
     byte[] bytes = new byte[str.Length * sizeof(char)]; 
     System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length); 
     return bytes; 
    } 

    static string GetString(byte[] bytes) 
    { 
     char[] chars = new char[bytes.Length/sizeof(char)]; 
     System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length); 
     return new string(chars); 
    } 

    public static String Encrypt(String strEncrypt) 
    { 
     byte[] userData = GetBytes(strEncrypt); 
     byte[] optionalEntropy = null; 
     byte[] x = System.Security.Cryptography.ProtectedData.Protect(userData, optionalEntropy); 
     return GetString(x); 
    } 
    public static String Decrypt(String strDecrypt) 
    { 
     byte[] encryptedData = GetBytes(strDecrypt); 
     byte[] optionalEntropy = null; 
     byte[] x = System.Security.Cryptography.ProtectedData.Unprotect(encryptedData, optionalEntropy); 
     return GetString(x); ; 
    }