2012-10-02 5 views
5

Je souhaite utiliser la cryptographie dans le Portable Class Library Contrib project on codeplex mais je n'ai trouvé aucune documentation sur la façon dont je peux l'utiliser.Bibliothèque de classes portable (PCL) Contrib - Cryptographie

Je souhaite créer une classe wrapper avec les méthodes Encrypt et Decrypt à l'intérieur et je souhaite que cette classe wrapper existe dans une bibliothèque de classes portable. J'ai référencé Portable.Runtime et Portable.Security.Cryptography dans ce projet. Est-ce correct? Je veux ensuite utiliser mon wrapper dans un projet .NET, Windows Phone et Metro. Dans ces projets, je référence mon projet wrapper, Portable.Runtime, Portable.Security.Cryptography et le projet Portable correspondant, c'est-à-dire Portable.Desktop, Portable.Phone ou Portable.WindowsStore. Est-ce correct?

Je rencontre des erreurs d'espace de noms conflictuelles lorsque j'essaie d'utiliser ma classe wrapper. Ceci est l'erreur et ma classe d'emballage:

Le type System.Security.Cryptography.AesManaged existe dans C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client\System.Core.dll et 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 vous avez résolu votre problème, afficher la solution comme une réponse, au lieu de le modifier dans la question. Ou avez-vous d'autres questions? Si oui, vous devriez les indiquer explicitement. – CodesInChaos

+1

btw votre utilisation IV est mauvaise. La IV devrait être différente pour chaque cryptage que vous effectuez. – CodesInChaos

Répondre

1

Il se trouve que mon emballage générique pour les algorithmes de cryptographie a été à l'origine d'un problème. PCL Contrib contient une classe appelée SymmetricAlgorithm qui est elle-même un wrapper pour le réel SymmetricAlgorithm. Si je fais ma classe d'emballage non générique, il fonctionne comme ceci:

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

Pouvez-vous également inclure un exemple de quelques lignes utilisant ces fonctions? –

+0

J'essaye également d'employer la cryptographie de pcl-contrib pour servir les applications de Windows Phone 8 et de magasin de fenêtres. donc j'ai fait copier votre code de la question et enlevé "scellé" de ce 'public class SymmetricCryptography où T: SymmetricAlgorithm, nouvelle() ....' donc je peux créer une version non générique de celui-ci, comme tu l'as suggéré. Pourriez-vous s'il vous plaît poster quelque part une solution en utilisant cela? –

+0

Vous avez utilisé 'this.provider.KeySize' mais le fournisseur est SymmetricAlgorithm et KeySize n'est pas associé? –

3

Les documents sont un peu défaut, mais j'appelle cela dans le FAQ:

Puis-je partager les types de PclContrib avec mes projets spécifiques à la plateforme? Non, pas actuellement. Alors que les types dans PclContrib ressemblent et que se sentent comme leurs homologues spécifiques à la plate-forme, le compilateur et Runtime les verront comme des types complètement différents. Alors que nous avons quelques idées sur la façon de faire ce travail, c'est une fonctionnalité que nous ne chercherons pas à court terme.

2

Le code .net suivant fonctionne sur l'implémentation Desktop. Tout d'abord ajouter des références à Portable.Desktop et 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); ; 
    } 
Questions connexes