2012-10-02 20 views
5

Quiero usar la criptografía en el Portable Class Library Contrib project on codeplex pero no he encontrado ninguna documentación sobre cómo puedo usarla.Portable Class Library (PCL) Contrib - Criptografía

Quiero crear una clase de contenedor con los métodos Encrypt y Decrypt y quiero que esta clase contenedora exista en una biblioteca de clases portátil. Me he referido a Portable.Runtime y Portable.Security.Cryptography en este proyecto. ¿Es esto correcto?

Luego quiero usar mi envoltorio dentro de un proyecto .NET, Windows Phone y Metro. En estos proyectos, hago referencia a mi proyecto de envoltura, Portable.Runtime, Portable.Security.Cryptography y el proyecto portátil correspondiente, es decir, Portable.Desktop, Portable.Phone o Portable.WindowsStore. ¿Es esto correcto?

Obtengo errores de espacio de nombres conflictivos cuando trato de usar mi clase contenedora sin embargo. Este es el error y mi clase de contenedor:

El tipo System.Security.Cryptography.AesManaged existe tanto en C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client\System.Core.dll y C:\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

Si usted ha resuelto su problema, publicar la solución como una respuesta, en lugar de editar en la pregunta. ¿O tienes alguna pregunta restante? Si es así, debe indicarlos explícitamente. – CodesInChaos

+1

por cierto, su uso IV es malo. La IV debe ser diferente para cada encriptación que realice. – CodesInChaos

Respuesta

1

Resulta que mi envoltorio genérico para los algoritmos de criptografía estaba causando un problema. PCL Contrib contiene una clase llamada SymmetricAlgorithm que es en sí misma un contenedor para el real SymmetricAlgorithm. Si hago mi clase contenedora no genérico funciona así:

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

¿También puede incluir un ejemplo de unas pocas líneas usando estas funciones? –

+0

También estoy tratando de usar la criptografía pcl-contrib para servir tanto a Windows Phone 8 como a Windows Store. así lo hice copiar el código de la pregunta y eliminado "sellado" de que 'SymmetricCryptography clase pública donde T: SymmetricAlgorithm, nuevo() ....' por lo que puede crear una versión no genérica de la misma, como sugirió. ¿Podría por favor publicar en alguna parte una solución usando esto? –

+0

Has usado 'this.provider.KeySize' pero el proveedor es SymmetricAlgorithm, y no tiene KeySize? –

3

Los documentos son un poco escaso, pero me llaman a esto en el FAQ:

¿Puedo compartir los tipos de PclContrib con mis proyectos específicos de plataforma? No, no actualmente. Mientras que los tipos en PclContrib look y se sienten como sus contrapartes específicas de plataforma, el compilador de tiempo de ejecución y los verá como tipos completamente diferentes. Si bien tenemos algunas ideas sobre cómo hacer que esto funcione, esta es una característica que no vamos a ver en el corto plazo.

2

El siguiente código .net funciona en la implementación de escritorio. En primer lugar añadir referencias a Portable.Desktop y 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); ; 
    } 
Cuestiones relacionadas