2017-09-17 5 views
0

J'ai eu le code andriod et j'ai essayé de le convertir en C#. C'est une classe de chiffrement simple. Mais quand j'essaye de décrypter des données avec cela, j'attrape: Wrong algorithm: AES or Rijndael required.
Voici mon code converti:Mauvais algorithme: AES ou Rijndael requis sur C#

public static string decrypt(string data) 
{ 
    byte[] dataBytes = Convert.FromBase64String(data); 
    SecretKey secretKey = getSecretKey(hashTheKey("ABCD")); 

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

    cipher.init(2, secretKey, new IvParameterSpec(new byte[16]), 
      SecureRandom.getInstance("SHA1PRNG")); 
    var x = cipher.doFinal(dataBytes); 
    return System.Text.Encoding.UTF8.GetString(x); 
} 
public static SecretKey getSecretKey(char[] key) 
{ 
    var secretKeyType = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
    var secretkey = secretKeyType.generateSecret(new PBEKeySpec(key, 
      System.Text.Encoding.UTF8 
       .GetBytes("ABCD"), 
      100, 128)).getEncoded(); 

    return new SecretKeySpec(secretkey, "AES/CBC/PKCS5Padding"); 
} 
public static char[] hashTheKey(string key) 
{ 
    MessageDigest messageDigest = MessageDigest.getInstance("SHA1"); 
    messageDigest.update(System.Text.Encoding.UTF8.GetBytes(key)); 
    return Convert.ToBase64String(messageDigest.digest()).ToCharArray(); 
} 

Voici mon original code Android:

private char[] hashTheKey(String key) throws UnsupportedEncodingException, NoSuchAlgorithmException { 
    MessageDigest messageDigest = MessageDigest.getInstance("SHA1"); 
    messageDigest.update(key.getBytes()); 
    return Base64.encodeToString(messageDigest.digest(), 
           Base64.NO_PADDING).toCharArray(); 
} 

private SecretKey getSecretKey(char[] key) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException { 
    return new SecretKeySpec(
     SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") 
     .generateSecret(new PBEKeySpec(key, 
         "ABCD".getBytes("UTF8"), 
         100, 128)).getEncoded(), "AES"); 
} 

public String decrypt(String data) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException, InvalidKeySpecException { 
    byte[] dataBytes = Base64.decode(data, Base64.DEFAULT); 
    SecretKey secretKey = getSecretKey(hashTheKey("ABCD")); 
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    cipher.init(2, secretKey, new IvParameterSpec(new byte[16]), 
      SecureRandom.getInstance("SHA1PRNG")); 
    return new String(cipher.doFinal(dataBytes)); 
} 
+0

Si vous essayez de convertir en C#, ** afficher le code C# **. –

+0

Je ne comprends pas. C'est écrit là !!! code converti. – David

+0

Qu'est-ce que this.mBuilder.getAlgorithm() 'renvoie dans votre code Android? – algrid

Répondre

1

et utilisent les mêmes algorithmes de cryptographie bien-établis, mais diffère dans l'approche comment les invoquer. Il est toujours possible de convertir le code.

Un point clé est la différence dans le codage base64 - C# utilise toujours un remplissage.

code converti va comme:

const int KeySize = 128; 

static string HashTheKey(string key) { 
    String hashKey; 
    using (var sha = new SHA1Managed()) { 
    hashKey = Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(key))); 
    } 
    // beware - you're on C# now so remove the padding and add the newline to match java 
    return hashKey.Replace("=", "") + "\n"; 
} 

static byte[] GetSecretKey(string password) { 
    var salt = Encoding.UTF8.GetBytes("JVAaVhAiddKAaghraikhmaini"); 
    using (var pass = new Rfc2898DeriveBytes(password, salt, 65536)) { 
    return pass.GetBytes(KeySize/8); 
    } 
} 

static void Main(string[] args) { 
    string encrypted = "vtlkQHTz7/oz2weuAAkLz2Q5c2yj2LGukF7SHJjT+TA8oRLixTQSXQ7dG1O736hyT1HJxcz0P4DzzVaO5chWKKSJQ2uPEpDQJu/fZGguqDw="; 
    byte[] encryptedBytes = Convert.FromBase64String(encrypted); 
    using (var aes = new AesManaged()) { 
    aes.KeySize = KeySize; 
    aes.Padding = PaddingMode.PKCS7; 
    aes.Key = GetSecretKey(HashTheKey("Android")); 
    // you're using the same init vector in your android code 
    aes.IV = new byte[16]; 
    using (var decryptor = aes.CreateDecryptor()) { 
     // dumps {"barcode":"12345678","token":"cad603fc-1e53-4a95-9150-f1694baa07f9"} 
     Console.Out.WriteLine(Encoding.UTF8.GetString(decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length))); 
    } 
    } 
} 
-2

C# ne gère pas les algorithmes de chiffrement comme Android ou Java ne vous devez utiliser AES ou l'algorithme Rijndael comme vous pouvez voir l'erreur secrète pour le texte simple dans Encrypted base64 et vous pouvez vice versa utiliser la classe suivante en C#

public static class Stringcipher 
    { 
     // This constant is used to determine the keysize of the encryption algorithm in bits. 
     // We divide this by 8 within the code below to get the equivalent number of bytes. 
     private const int Keysize = 256; 

     // This constant determines the number of iterations for the password bytes generation function. 
     private const int DerivationIterations = 1000; 

     public static string Encrypt(string plainText, string passPhrase) 
     { 
      // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text 
      // so that the same Salt and IV values can be used when decrypting. 
      var saltStringBytes = Generate256BitsOfRandomEntropy(); 
      var ivStringBytes = Generate256BitsOfRandomEntropy(); 
      var plainTextBytes = Encoding.UTF8.GetBytes(plainText); 
      using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations)) 
      { 
       var keyBytes = password.GetBytes(Keysize/8); 
       using (var symmetricKey = new RijndaelManaged()) 
       { 
        symmetricKey.BlockSize = 256; 
        symmetricKey.Mode = CipherMode.CBC; 
        symmetricKey.Padding = PaddingMode.PKCS7; 
        using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes)) 
        { 
         using (var memoryStream = new MemoryStream()) 
         { 
          using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) 
          { 
           cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); 
           cryptoStream.FlushFinalBlock(); 
           // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes. 
           var cipherTextBytes = saltStringBytes; 
           cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray(); 
           cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray(); 
           memoryStream.Close(); 
           cryptoStream.Close(); 
           return Convert.ToBase64String(cipherTextBytes); 
          } 
         } 
        } 
       } 
      } 
     } 

     public static string Decrypt(string cipherText, string passPhrase) 
     { 
      // Get the complete stream of bytes that represent: 
      // [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText] 
      var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText); 
      // Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes. 
      var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize/8).ToArray(); 
      // Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes. 
      var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize/8).Take(Keysize/8).ToArray(); 
      // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string. 
      var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize/8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize/8) * 2)).ToArray(); 

      using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations)) 
      { 
       var keyBytes = password.GetBytes(Keysize/8); 
       using (var symmetricKey = new RijndaelManaged()) 
       { 
        symmetricKey.BlockSize = 256; 
        symmetricKey.Mode = CipherMode.CBC; 
        symmetricKey.Padding = PaddingMode.PKCS7; 
        using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes)) 
        { 
         using (var memoryStream = new MemoryStream(cipherTextBytes)) 
         { 
          using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) 
          { 
           var plainTextBytes = new byte[cipherTextBytes.Length]; 
           var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); 
           memoryStream.Close(); 
           cryptoStream.Close(); 
           return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount); 
          } 
         } 
        } 
       } 
      } 
     } 

     private static byte[] Generate256BitsOfRandomEntropy() 
     { 
      var randomBytes = new byte[32]; // 32 Bytes will give us 256 bits. 
      using (var rngCsp = new RNGCryptoServiceProvider()) 
      { 
       // Fill the array with cryptographically secure random bytes. 
       rngCsp.GetBytes(randomBytes); 
      } 
      return randomBytes; 
     } 
    } 
+0

merci. mais comment puis-je créer PassPhrase? Je suppose qu'il devrait générer à partir de ENCRYPTION_KEY, sel et iv. ai-je raison? – David

+0

peu importe d'où vous l'avez créé c'est juste la chaîne unique afin qu'il s'assure que seulement votre application/code le déchiffre. . . –

+0

mais je veux déchiffrer la chaîne. pas crypter. en fait la chaîne déjà cryptée par le client android et je dois le décrypter !! – David