AES 256 Text Encryption возвращает разные значения - PullRequest
1 голос
/ 22 марта 2019

Я пытаюсь скопировать метод шифрования на основе другого C# метода, который я нашел.

C# Метод шифрования EncryptText(word, password) вызов другого метода AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes) для шифрования простого текста:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.IO;
using System.Text;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var f = EncryptText("763059", "515t3ma5m15B4d35");//(word, password)
            Console.WriteLine(f);
        }

        public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
        {
            byte[] encryptedBytes = null;
            byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

            using (MemoryStream ms = new MemoryStream())
            {
                using (RijndaelManaged AES = new RijndaelManaged())
                {
                    AES.KeySize = 256;
                    AES.BlockSize = 128;

                    var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
                    AES.Key = key.GetBytes(AES.KeySize / 8);
                    AES.IV = key.GetBytes(AES.BlockSize / 8);

                    AES.Mode = CipherMode.CBC;

                    using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                        cs.Close();
                    }
                    encryptedBytes = ms.ToArray();
                }
            }

            return encryptedBytes;
        }

        public static string EncryptText(string input, string password)
        {
            byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(input);
            byte[] passwordBytes = Encoding.UTF8.GetBytes(password);

            passwordBytes = SHA256.Create().ComputeHash(passwordBytes);

            byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);
            string result = Convert.ToBase64String(bytesEncrypted);

            return result;
        }
    }
}

Используя слово 763059 и пароль 515t3ma5m15B4d35 , вывод будет следующим:

3cHrXxxL1Djv0K2xW4HuCg ==

UPDATE:

Теперь я создал Java Class main, где я пытаюсь повторить предыдущий код:

public class main {

    final static String PASSWORD = "515t3ma5m15B4d35";
    final static byte[] SALT = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};
    final static int KEY_SIZE = 256;
    final static int BLOCK_SIZE = 128;
    final static int ITERATIONS = 1000;

    public static void main(String[] args) {
        System.out.println(encryptText("763059", PASSWORD));
    }

    public static String encryptText(String word, String password) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(password.getBytes("UTF-8"));
            password = new String(md.digest(), "UTF-8");

            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            KeySpec spec = new PBEKeySpec(password.toCharArray(), SALT, ITERATIONS, KEY_SIZE);
            SecretKey tmp = factory.generateSecret(spec);
            SecretKeySpec skey = new SecretKeySpec(tmp.getEncoded(), "AES");

            byte[] iv = new byte[BLOCK_SIZE / 8];
            IvParameterSpec ivspec = new IvParameterSpec(iv);
            Cipher ci = Cipher.getInstance("AES/CBC/PKCS5Padding");
            ci.init(Cipher.ENCRYPT_MODE, skey, ivspec);
            byte[] result = ci.doFinal(word.getBytes("UTF-8"));

            return DatatypeConverter.printBase64Binary(result);

        } catch (NoSuchAlgorithmException | UnsupportedEncodingException | IllegalBlockSizeException | BadPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | NoSuchPaddingException | InvalidKeySpecException ex) {
            return null;
        }
    }

}

UPDATE:

Я читал об использовании 256-битных ключей в Java и обнаружил, что мне нужно добавить Java Cryptography Extensions , чтобы разрешить 256 ключей (, потому что я работаю с JDK7 ).

Затем я добавил библиотеки в проект, также я изменил строку:

KeySpec spec = new PBEKeySpec(password.toCharArray(), SALT, ITERATIONS, KEY_SIZE);

со значением ключа:

final static int KEY_SIZE = 256;

Теперь вывод выглядит следующим образом:

J1xbKOjIeXbQ9njH + 67RNw ==

Я все еще не могу достичь своей цели. Любое предложение?

Ответы [ 2 ]

0 голосов
/ 30 марта 2019

Наконец, я решил использовать API BouncyCastle для использования функциональности RijndaelEngine, а также для генерации 256-битного ключа с PKCS5S2ParametersGenerator.

Я создал класс RijndaelEncryption, чтобы иметь возможность выполнять шифрование, как в коде C #:

public class RijndaelEncryption {

    public String encryptString(String word, String password, byte[] salt, int iterations, int keySize, int blockSize) {
        try {
            byte[] pswd = sha256String(password, "UTF-8");
            PKCS5S2ParametersGenerator key = keyGeneration(pswd, salt, iterations);
            ParametersWithIV iv = generateIV(key, keySize, blockSize);
            BufferedBlockCipher cipher = getCipher(true, iv);
            byte[] inputText = word.getBytes("UTF-8");
            byte[] newData = new byte[cipher.getOutputSize(inputText.length)];
            int l = cipher.processBytes(inputText, 0, inputText.length, newData, 0);
            cipher.doFinal(newData, l);
            return new String(Base64.encode(newData), "UTF-8");
        } catch (UnsupportedEncodingException | IllegalStateException | DataLengthException | InvalidCipherTextException e) {
            return null;
        }
    }

    public BufferedBlockCipher getCipher(boolean encrypt, ParametersWithIV iv) {
        RijndaelEngine rijndael = new RijndaelEngine();
        BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(rijndael));
        cipher.init(encrypt, iv);
        return cipher;
    }

    public ParametersWithIV generateIV(PKCS5S2ParametersGenerator key, int keySize, int blockSize) {
        try {
            ParametersWithIV iv = null;
            iv = ((ParametersWithIV) key.generateDerivedParameters(keySize, blockSize));
            return iv;
        } catch (Exception e) {
            return null;
        }
    }

    public PKCS5S2ParametersGenerator keyGeneration(byte[] password, byte[] salt, int iterations) {
        try {
            PKCS5S2ParametersGenerator key = new PKCS5S2ParametersGenerator();
            key.init(password, salt, iterations);
            return key;
        } catch (Exception e) {
            return null;
        }
    }

    public byte[] sha256String(String password, Charset charset) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(password.getBytes(charset));
            return md.digest();
        } catch (NoSuchAlgorithmException ex) {
            return null;
        }
    }

    public byte[] sha256String(String password, String charset) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(password.getBytes(charset));
            return md.digest();
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) {
            return null;
        }
    }
}

И я тестировал main метод:

public static void main(String[] args) {
     RijndaelEncryption s = new RijndaelEncryption();
     byte[] salt = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};
     String encryptStr = s.encryptString("763059", "515t3ma5m15B4d35", salt, 1000, 256, 128);
     System.out.println("Encryptation: " + encryptStr);
}

Чтобы получить:

Шифрование: 3cHrXxxL1Djv0K2xW4HuCg ==

0 голосов
/ 22 марта 2019

Я не эксперт по C #, но есть несколько вещей, которые нужно проверить:

Чтение документации о Rfc2898DeriveBytes Я вижу, что функция использует хэш SHA1, поэтому попробуйтепопробуйте использовать PBKDF2WithHmacSHA1

В обоих случаях (Rfc2898DeriveBytes, PBEKeySpec) вы должны убедиться, что размер ключа одинаков (256 бит), это, безусловно, неверно в вашем коде Java

Вы можетеПопробуйте закодировать и распечатать ключи, чтобы убедиться, что они одинаковы.

Мне нужно добавить Расширения Java Cryptography, чтобы разрешить 256 ключей.

Зависит от вашей версии JVM.Я считаю, что Oracle JDK, поскольку v. 1.8u162 по умолчанию содержит политику JCE Unlimited Strength.Если вы используете любую текущую версию JRE, у вас должно быть все в порядке

Дополнительно: вы используете (статический) нулевой массив IV, который не является безопасным

...