Как получить AES 256 ключевых параметров для использования в Java и CSharp сети - PullRequest
0 голосов
/ 23 апреля 2020

Итак, у меня есть код в Java для шифрования и дешифрования объектов, и я пытался сделать то же самое в C#, чтобы мой сервер и клиент могли расшифровывать и шифровать сообщения. Я получил большую часть его для работы, за исключением того, что я пропускаю только ключевые параметры для Java.

@RequiredArgsConstructor
@Getter
public class EncryptedBytes {

    private final byte[] data;
    private final byte[] params;
    private final String paramAlgorithm;

}

    /**
     * Encrypt object with password
     *
     * @param data   Object to be encrypted
     * @param secret Password to use for encryption
     * @return Encrypted version of object
     */
    public static EncryptedBytes encrypt(String data, SecretKey secret) throws InvalidKeyException {

        try {
            Cipher cipher = Cipher.getInstance(StaticHandler.AES_CIPHER_TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, secret);

            // properly encode the complete ciphertext
            //logEncrypt(password, object);

            byte[] encodedData = cipher.doFinal(data.getBytes(StaticHandler.CHARSET_FOR_STRING));
            byte[] params = cipher.getParameters().getEncoded();
            String paramAlgorithm = cipher.getParameters().getAlgorithm();

            return new EncryptedBytes(encodedData, params, paramAlgorithm);
        } catch (InvalidKeyException e) {
            throw e;
        } catch (NoSuchAlgorithmException | IllegalBlockSizeException | NoSuchPaddingException | BadPaddingException | IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Decrypt data with secret
     *
     * @param encryptedBytes Object to be decrypted
     * @param secret         Password to use for decryption
     * @return Decrypted version of object
     */
    public static String decrypt(EncryptedBytes encryptedBytes, @NonNull SecretKey secret) throws InvalidKeyException {
        try {

            // get parameter object for password-based encryption
            AlgorithmParameters algParams = AlgorithmParameters.getInstance(encryptedBytes.getParamAlgorithm());


            if (algParams == null) throw new IllegalArgumentException("EncryptedBytes.Parameters are not valid");

            // initialize with parameter encoding from above
            algParams.init(encryptedBytes.getParams());

            Cipher cipher = Cipher.getInstance(StaticHandler.AES_CIPHER_TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, secret, algParams);

            return new String(cipher.doFinal(encryptedBytes.getData()), StaticHandler.CHARSET_FOR_STRING);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | IOException | InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
        return null;
    }

Теперь в C# у меня есть очень близкая реализация к коду Java выше. Я пропускаю только данные параметров для Java.

   public class EncryptedBytes
    {
        public List<byte> data { get; }

        [JsonProperty("params")]
        [JsonPropertyName("params")]
        public List<byte> keyParams { get;  }

        public string paramAlgorithm { get; }

        public EncryptedBytes(IEnumerable<byte> data, IEnumerable<byte> keyParams, string paramAlgorithm)
        {
            this.data = data.ToList();
            this.keyParams = keyParams.ToList();
            this.paramAlgorithm = paramAlgorithm;
        }
    }

        public static EncryptedBytes encrypt(AesCryptoServiceProvider aesCryptoServiceProvider, string plainText,
            Encoding encoding)
        {
            if (encoding == null) encoding = StaticHandler.encoding;

            // Check arguments.
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (aesCryptoServiceProvider.Key == null || aesCryptoServiceProvider.Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (aesCryptoServiceProvider.IV == null || aesCryptoServiceProvider.IV.Length <= 0)
                throw new ArgumentNullException("IV");


            ICryptoTransform transform = aesCryptoServiceProvider.CreateEncryptor();

            return encrypt(transform, /* find paramater here */, plainText, encoding);
        }

        public static EncryptedBytes encrypt(ICryptoTransform transform, byte[] par, string plainText, Encoding encoding)
        {
            if (encoding == null) encoding = StaticHandler.encoding;

            // Check arguments.
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException(nameof(plainText));


            var encodedText = encoding.GetBytes(plainText);
            var encryptedText =
                transform.TransformFinalBlock(encodedText, 0, encodedText.Length);

            return new EncryptedBytes(encryptedText, par, "AES");
        }

        public static string decrypt(EncryptedBytes encryptedBytes, AesCryptoServiceProvider aesCryptoServiceProvider, Encoding? encoding)
        {
            if (encoding == null) encoding = StaticHandler.encoding;

            byte[] cipherText = encryptedBytes.data.ToArray();

            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (aesCryptoServiceProvider.Key == null || aesCryptoServiceProvider.Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (aesCryptoServiceProvider.IV == null || aesCryptoServiceProvider.IV.Length <= 0)
                throw new ArgumentNullException("IV");

            // Declare the string used to hold
            // the decrypted text.

            ICryptoTransform transform = aesCryptoServiceProvider.CreateDecryptor();

            var plaintext = encoding.GetString(transform.TransformFinalBlock(cipherText, 0, cipherText.Length));

            return plaintext;

        }

Основной код, о котором идет речь:

encrypt

            ICryptoTransform transform = aesCryptoServiceProvider.CreateEncryptor();

            return encrypt(transform, /* find paramater here */, plainText, encoding);

и расшифровывает

            ICryptoTransform transform = aesCryptoServiceProvider.CreateDecryptor();

            var plaintext = encoding.GetString(transform.TransformFinalBlock(cipherText, 0, cipherText.Length));

            return plaintext;

Мне нужен способ получить ключевые параметры для Java, чтобы использовать их для расшифровки и использовать параметры java для расшифровки в C#, если необходимо.

Редактировать

Хорошо, у меня работает шифрование. Теперь мне нужно, чтобы расшифровка работала. Проблема в том, что для расшифровки используются данные, отправленные Java байтами, и, очевидно, Newtonsoft JSON не может десериализовать их должным образом, используя byte [], поэтому вместо этого я использую sbyte []. Дело в том, что для расшифровки кода требуется байт [], и я попытался привести и преобразовать sbyte [] в байты с помощью приведения и Convert.ToByte (), и ни один из них не сработал. Самое близкое, что я получил, это приведение sbyte к байту, однако при запуске нового байта [] с transform.TransformFinalBlock(cipherText, 0, cipherText.Length) я получаю исключение искаженного заполнения, даже если я использую заполнение PCKS7 на обоих (а точнее PCKS5 на Java)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...