AESCrypt от Java до c# - PullRequest
       8

AESCrypt от Java до c#

0 голосов
/ 28 февраля 2020

Я играл с этой библиотекой: https://github.com/scottyab/AESCrypt-Android и я хотел бы воспроизвести такое же поведение с c#, кто-нибудь знает хороший способ сделать это? Я перепробовал много библиотек AESCrypt, но ни одна из них, похоже, не справляется правильно с пустым IV.

Спасибо

Ответы [ 2 ]

0 голосов
/ 28 февраля 2020

Мой ответ совместим с шифрованием. Результат можно расшифровать с любой платформы - код C# или код Android / Java.

  • Зашифровать с C# -> Расшифровать с C#, Android, Java.
  • Зашифровать с Android -> Расшифровать с Android, Java, C#.
  • Шифрование из Java -> Дешифрование из Java, Android, C#.
  • Результат шифрования содержит зашифрованный текст + IV ,
  • IV генерируется с использованием безопасного случайного алгоритма.

Процесс шифрования
1. открытый текст => plaintextBytes
2. пароль => passwordBytes => Sha256 (passwordbytes) = passwordHashBytes
3. генерировать случайные IV байт = ivBytes
4. шифрование с использованием незашифрованных байтов и passwordHashBytes
5. соединение (encryptedbytes + ivBytes)
6. Преобразование в объединенные байты base64.

C# Реализация

public enum HashAlgorithm
{
    MD5,
    SHA1,
    SHA256,
    SHA384,
    SHA512
}

public class HashManager {
    public static byte[] ToRawHash(byte[] data, HashAlgorithm algorithm)
    {
        byte[] hash;
        switch (algorithm)
        {
            case HashAlgorithm.MD5:
                MD5 md5 = MD5.Create();
                hash = md5.ComputeHash(data, 0, data.Length);
                return hash;
            case HashAlgorithm.SHA1:
                SHA1Managed sha1 = new SHA1Managed();
                hash = sha1.ComputeHash(data);
                return hash;
            case HashAlgorithm.SHA256:
                SHA256Managed sha256 = new SHA256Managed();
                hash = sha256.ComputeHash(data);
                return hash;
            case HashAlgorithm.SHA384:
                SHA384Managed sha384 = new SHA384Managed();
                hash = sha384.ComputeHash(data);
                return hash;
            case HashAlgorithm.SHA512:
                SHA512Managed sha512 = new SHA512Managed();
                hash = sha512.ComputeHash(data, 0, data.Length);
                return hash;
            default:
                throw new ArgumentException("Invalid Algorithm");
        }
    }
}

public class Base64Manager
{
    public static byte[] Base64ToByteArray(String base64)
    {
        return Convert.FromBase64String(base64);
    }

    public static String ToBase64(byte[] data, Boolean insertLineBreaks = default(Boolean))
    {
        return insertLineBreaks ? Convert.ToBase64String(data, Base64FormattingOptions.InsertLineBreaks) : Convert.ToBase64String(data);
    }
}

public class AesManager
{
    private const int MAX_IV_LENGTH = 16;
    private const int MAX_KEY_LENGTH = 32;

    private static byte[] GenerateValidKey(byte[] keyBytes)
    {
        byte[] ret = new byte[MAX_KEY_LENGTH];
        byte[] hash = HashManager.ToRawHash(keyBytes, HashAlgorithm.SHA256);
        Array.Copy(hash, ret, MAX_KEY_LENGTH);
        return ret;
    }


    public static byte[] EncryptRaw(byte[] PlainBytes, byte[] Key)
    {
        AesManaged AesAlgorithm = new AesManaged()
        {
            Key = GenerateValidKey(Key)
        };
        AesAlgorithm.GenerateIV();
        var Encrypted = AesAlgorithm.CreateEncryptor().TransformFinalBlock(PlainBytes, 0, PlainBytes.Length);
        byte[] ret = new byte[Encrypted.Length + MAX_IV_LENGTH];
        Array.Copy(Encrypted, ret, Encrypted.Length);
        Array.Copy(AesAlgorithm.IV, 0, ret, ret.Length - MAX_IV_LENGTH, MAX_IV_LENGTH);
        return ret;
    }

    public static byte[] DecryptRaw(byte[] CipherBytes, byte[] Key)
    {
        AesManaged AesAlgorithm = new AesManaged()
        {
            Key = GenerateValidKey(Key)
        };
        byte[] IV = new byte[MAX_IV_LENGTH];
        Array.Copy(CipherBytes, CipherBytes.Length - MAX_IV_LENGTH, IV, 0, MAX_IV_LENGTH);
        AesAlgorithm.IV = IV;
        byte[] RealBytes = new byte[CipherBytes.Length - MAX_IV_LENGTH];
        Array.Copy(CipherBytes, RealBytes, CipherBytes.Length - MAX_IV_LENGTH);
        return AesAlgorithm.CreateDecryptor().TransformFinalBlock(RealBytes, 0, RealBytes.Length); ;
    }


    public static String EncryptToBase64(String Plaintext, String Key)
    {
        byte[] PlainBytes = Encoding.UTF8.GetBytes(Plaintext);
        return Base64Manager.ToBase64(EncryptRaw(PlainBytes, Encoding.UTF8.GetBytes(Key)), false);
    }



    public static String DecryptFromBase64(String CipherText, String Key)
    {
        byte[] CiPherBytes = Base64Manager.Base64ToByteArray(CipherText);
        byte[] Encrypted = DecryptRaw(CiPherBytes, Encoding.UTF8.GetBytes(Key));
        return Encoding.UTF8.GetString(Encrypted, 0, Encrypted.Length);
    }

}

class Program
{

    static void Main(string[] args)
    {
        string plainText = "plain text";
        string password = "password";
        string encrypted = AesManager.EncryptToBase64(plainText, password);
        Console.WriteLine(AesManager.DecryptFromBase64(encrypted, password));
        Console.ReadLine();
    }
}

Android / Java Реализация

public enum HashAlgorithm {

    SHA512("SHA-512"),
    SHA256("SHA-256"),
    SHA384("SHA-384"),
    SHA1("SHA-1"),
    MD5("MD5");

    private String Value = "";

    HashAlgorithm(String Value) {
        this.Value = Value;
    }

    @Override
    public String toString() {
        return Value;
    }

}

import java.security.MessageDigest;
public class HashManager {
    public static byte[] toRawHash(byte[] data,
                                   HashAlgorithm algorithm) throws Exception
    {
        byte[] buffer = data;
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm.toString());
        messageDigest.reset();
        messageDigest.update(buffer);
        return messageDigest.digest();
    }
}

Base64Manager class Android реализация

import android.util.Base64;

public class Base64Manager {
    public static String toBase64(byte[] data,
                                  boolean insertLineBreaks) throws Exception
    {
        String ret;
        if (insertLineBreaks)
        {
            ret = Base64.encodeToString(data, Base64.DEFAULT);
        }
        else
        {
            ret = Base64.encodeToString(data, Base64.NO_WRAP);
        }
        return ret;
    }

    public static String toBase64(String data,
                                  boolean insertLineBreaks) throws Exception
    {
        return toBase64(data.getBytes("UTF-8"), insertLineBreaks);
    }

    public static byte[] base64ToByteArray(String base64) throws Exception
    {
        return base64.contains(System.getProperty("line.separator")) ? Base64.decode(base64, Base64.DEFAULT) : Base64.decode(base64, Base64.NO_WRAP);
    }
}

Base64Manager класс Java8 + реализация

import java.util.Base64;

public class Base64Manager {    
    public static String toBase64(byte[] data, Boolean insertLineBreaks) throws Exception {
        String ret;
        if (insertLineBreaks) {
            ret = Base64.getMimeEncoder().encodeToString(data);
        } else {
            ret = Base64.getEncoder().encodeToString(data);
        }
        return ret;
    }

    public static String toBase64(String data, Boolean insertLineBreaks) throws Exception {
        return toBase64(data.getBytes("UTF-8" ), insertLineBreaks);
    }

    public static byte[] base64ToByteArray(String base64) throws Exception {
        return base64.contains(System.getProperty("line.separator")) ? Base64.getMimeDecoder().decode(base64) : Base64.getDecoder().decode(base64);
    }    
}


import java.security.SecureRandom;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AesManager {

    private static final int MAX_IV_LENGTH = 16;
    private static final int MAX_KEY_LENGTH = 32;

    public static String decryptFromBase64(String cipherText, String key) throws Exception {
        byte[] CiPherBytes = Base64Manager.base64ToByteArray(cipherText);
        byte[] KeyBytes = key.getBytes("UTF-8");
        return new String((decryptRaw(CiPherBytes, KeyBytes)));
    }

    public static byte[] generateValidKey(byte[] key) throws Exception {
        return Arrays.copyOf(HashManager.toRawHash(key, HashAlgorithm.SHA256), MAX_KEY_LENGTH);
    }


    public static byte[] decryptRaw(byte[] cipherBytes, byte[] keyBytes) throws Exception {
        byte[] IV = Arrays.copyOfRange(cipherBytes, cipherBytes.length - MAX_IV_LENGTH, cipherBytes.length);
        byte[] RealBytes = Arrays.copyOf(cipherBytes, cipherBytes.length - MAX_IV_LENGTH);
        Cipher AesAlgorithm = Cipher.getInstance("AES/CBC/PKCS5Padding" );
        byte[] ValidKeyBytes = generateValidKey(keyBytes);
        SecretKeySpec secretKeySpec = new SecretKeySpec(ValidKeyBytes, "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(IV);
        AesAlgorithm.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
        byte[] Decrypted = AesAlgorithm.doFinal(RealBytes);
        return Decrypted;
    }

    public static byte[] encryptRaw(byte[] plainBytes, byte[] keyBytes) throws Exception {
        Cipher AesAlgorithm = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] ValidKeyBytes = generateValidKey(keyBytes);
        SecretKeySpec secretKeySpec = new SecretKeySpec(ValidKeyBytes, "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(generateIV());
        AesAlgorithm.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        byte[] Encrypted = AesAlgorithm.doFinal(plainBytes);
        byte[] ret = new byte[Encrypted.length + MAX_IV_LENGTH];
        System.arraycopy(Encrypted, 0, ret, 0, Encrypted.length);
        System.arraycopy(ivParameterSpec.getIV(), 0, ret, Encrypted.length, MAX_IV_LENGTH);
        return ret;
    }

    private static byte[] generateIV() throws Exception {
        return generateRandomArray(MAX_IV_LENGTH);
    }

    public static byte[] generateRandomArray(int size) {
        SecureRandom RandomGenerator = new SecureRandom();
        byte[] ret = new byte[size];
        RandomGenerator.nextBytes(ret);
        return ret;
    }

    public static String encryptToBase64(String plaintext, String key) throws Exception {
        byte[] PlainBytes = plaintext.getBytes("UTF-8");
        byte[] KeyBytes = key.getBytes("UTF-8");
        return Base64Manager.toBase64(encryptRaw(PlainBytes, KeyBytes), false);
    }

}

public class Program {
    public static  void main(String[] args) throws Exception
    {
        String plainText = "plain text";
        String password = "password";
        String encrypted = AesManager.encryptToBase64(plainText, password);
        System.out.println(AesManager.decryptFromBase64(encrypted, password));
    }
}
0 голосов
/ 28 февраля 2020

Нашел это, что полностью отвечает моим потребностям Преобразование функции шифрования и дешифрования C# в PHP функцию

    public string EncryptString(string plainText, byte[] key, byte[] iv)
{
    // Instantiate a new Aes object to perform string symmetric encryption
    Aes encryptor = Aes.Create();

    encryptor.Mode = CipherMode.CBC;

    // Set key and IV
    byte[] aesKey = new byte[32];
    Array.Copy(key, 0, aesKey, 0, 32);
    encryptor.Key = aesKey;
    encryptor.IV = iv;

    // Instantiate a new MemoryStream object to contain the encrypted bytes
    MemoryStream memoryStream = new MemoryStream();

    // Instantiate a new encryptor from our Aes object
    ICryptoTransform aesEncryptor = encryptor.CreateEncryptor();

    // Instantiate a new CryptoStream object to process the data and write it to the 
    // memory stream
    CryptoStream cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write);

    // Convert the plainText string into a byte array
    byte[] plainBytes = Encoding.ASCII.GetBytes(plainText);

    // Encrypt the input plaintext string
    cryptoStream.Write(plainBytes, 0, plainBytes.Length);

    // Complete the encryption process
    cryptoStream.FlushFinalBlock();

    // Convert the encrypted data from a MemoryStream to a byte array
    byte[] cipherBytes = memoryStream.ToArray();

    // Close both the MemoryStream and the CryptoStream
    memoryStream.Close();
    cryptoStream.Close();

    // Convert the encrypted byte array to a base64 encoded string
    string cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length);

    // Return the encrypted data as a string
    return cipherText;
}

public string DecryptString(string cipherText, byte[] key, byte[] iv)
{
    // Instantiate a new Aes object to perform string symmetric encryption
    Aes encryptor = Aes.Create();

    encryptor.Mode = CipherMode.CBC;

    // Set key and IV
    byte[] aesKey = new byte[32];
    Array.Copy(key, 0, aesKey, 0, 32);
    encryptor.Key = aesKey;
    encryptor.IV = iv;

    // Instantiate a new MemoryStream object to contain the encrypted bytes
    MemoryStream memoryStream = new MemoryStream();

    // Instantiate a new encryptor from our Aes object
    ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();

    // Instantiate a new CryptoStream object to process the data and write it to the 
    // memory stream
    CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);

    // Will contain decrypted plaintext
    string plainText = String.Empty;

    try
    {
        // Convert the ciphertext string into a byte array
        byte[] cipherBytes = Convert.FromBase64String(cipherText);

        // Decrypt the input ciphertext string
        cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);

        // Complete the decryption process
        cryptoStream.FlushFinalBlock();

        // Convert the decrypted data from a MemoryStream to a byte array
        byte[] plainBytes = memoryStream.ToArray();

        // Convert the decrypted byte array to string
        plainText = Encoding.ASCII.GetString(plainBytes, 0, plainBytes.Length);
    }
    finally
    {
        // Close both the MemoryStream and the CryptoStream
        memoryStream.Close();
        cryptoStream.Close();
    }

    // Return the decrypted data as a string
    return plainText;
}

private void button1_Click(object sender, EventArgs e)
{
    string message = "My secret message 1234";
    string password = "3sc3RLrpd17";

    // Create sha256 hash
    SHA256 mySHA256 = SHA256Managed.Create();
    byte[] key = mySHA256.ComputeHash(Encoding.ASCII.GetBytes(password));

    // Create secret IV
    byte[] iv = new byte[16] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };

    string encrypted = this.EncryptString(message, key, iv);
    string decrypted = this.DecryptString(encrypted, key, iv);

    Console.WriteLine(encrypted);
    Console.WriteLine(decrypted);
}
...