Почему шифрование RSA в Java создает зашифрованный текст другой длины, чем в C # - PullRequest
1 голос
/ 11 июля 2019

Я AES шифрую некоторый текст, используя случайно сгенерированный ключ, а затем RSA шифрую этот ключ с помощью закрытого ключа, чтобы я мог загрузить его в базу данных.

Ключи RSA создаются с использованием KeyPairGenerator в Java и сохраняются в виде файла. Ключи читаются с использованием File.ReadAllBytes().

Когда я делаю это в Java, все работает отлично, и зашифрованный ключ всегда 172 bytes, но когда я делаю это в C#, зашифрованный ключ всегда 844 bytes. Я почти уверен, что текст правильно шифруется с использованием AES, но что-то не так с шифрованием RSA.

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

Java

public String encryptText(String msg, PrivateKey key) 
            throws NoSuchAlgorithmException, NoSuchPaddingException,
            UnsupportedEncodingException, IllegalBlockSizeException, 
            BadPaddingException, InvalidKeyException {

        KeyGenerator generator;   
        this.cipher.init(Cipher.ENCRYPT_MODE, key); //cipher is initialized earlier with this.cipher = Cipher.getInstance("RSA");

            try {
                generator = KeyGenerator.getInstance(AES);
                generator.init(128); // The AES key size in number of bits
                SecretKey secKey = generator.generateKey();

                Cipher aesCipher = Cipher.getInstance(AES);
                aesCipher.init(Cipher.ENCRYPT_MODE, secKey);

                String encText = Base64.getEncoder().encodeToString(aesCipher.doFinal(msg.getBytes("UTF-8")));
                String encKey = Base64.getEncoder().encodeToString(cipher.doFinal(secKey.getEncoded()));

                return "(" + encText + ")" + encKey;                
            } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        return null;
    }

C #

public String EncryptText(byte[] privateKeyBytes, string msg)
        {
            try
            {
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
                RSAParameters RSAKeyInfo = RSA.ExportParameters(false);

                RSAKeyInfo.Modulus = privateKeyBytes;
                RSA.ImportParameters(RSAKeyInfo);

                RijndaelManaged aes = new RijndaelManaged();
                aes.BlockSize = 128;
                aes.KeySize = 128;
                aes.Mode = CipherMode.ECB;
                byte[] keyGenerated = aes.Key;

                string keyStr = Convert.ToBase64String(keyGenerated);
                byte[] keyArr = Convert.FromBase64String(keyStr);
                byte[] KeyArrBytes16Value = new byte[16];
                Array.Copy(keyArr, KeyArrBytes16Value, 16);

                aes.Key = KeyArrBytes16Value;

                ICryptoTransform encrypto = aes.CreateEncryptor();

                byte[] plainTextByte = ASCIIEncoding.UTF8.GetBytes(msg);
                byte[] CipherText = encrypto.TransformFinalBlock(plainTextByte, 0, plainTextByte.Length);

                string encText = Convert.ToBase64String(CipherText);
                string encKey = Convert.ToBase64String(RSA.Encrypt(aes.Key, true));

                return "(" + encText + ")" + encKey;

            }
            catch (CryptographicException e)
            {
                Console.WriteLine("FAILED: " + e.Message);
            }

            return null;
        }

UPDATE
Спасибо Хенно за то, что указал, что проблема была в том, как я читал ключ. В итоге я использовал Bouncy Castle для обработки шифрования RSA в C #. Я также изменил свой код Java для шифрования с открытым ключом вместо закрытого ключа.

Новый C #

public String EncryptText(byte[] keyBytes, string msg)
        {
            try
            {
                AsymmetricKeyParameter asymmetricKeyParameter = PublicKeyFactory.CreateKey(keyBytes);
                RsaKeyParameters rsaKeyParameters = (RsaKeyParameters)asymmetricKeyParameter;
                RSAParameters rsaParameters = new RSAParameters();
                rsaParameters.Modulus = rsaKeyParameters.Modulus.ToByteArrayUnsigned();
                rsaParameters.Exponent = rsaKeyParameters.Exponent.ToByteArrayUnsigned();
                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                rsa.ImportParameters(rsaParameters);

                RijndaelManaged aes = new RijndaelManaged();
                aes.BlockSize = 128;
                aes.KeySize = 128;
                aes.Mode = CipherMode.ECB;
                byte[] keyGenerated = aes.Key;

                string keyStr = Convert.ToBase64String(keyGenerated);
                byte[] keyArr = Convert.FromBase64String(keyStr);
                byte[] KeyArrBytes16Value = new byte[16];
                Array.Copy(keyArr, KeyArrBytes16Value, 16);

                aes.Key = KeyArrBytes16Value;

                ICryptoTransform encrypto = aes.CreateEncryptor();

                byte[] plainTextByte = ASCIIEncoding.UTF8.GetBytes(msg);
                byte[] CipherText = encrypto.TransformFinalBlock(plainTextByte, 0, plainTextByte.Length);

                string encText = Convert.ToBase64String(CipherText);
                string encKey = Convert.ToBase64String(rsa.Encrypt(aes.Key, false));

                return "(" + encText + ")" + encKey;

            }
            catch (CryptographicException e)
            {
                Console.WriteLine("FAILED: " + e.Message);
            }

            return null;
        }

1 Ответ

1 голос
/ 11 июля 2019

Что кажется неправильным, так это то, что вы читаете в сохраненном «файле закрытого ключа» в C #, предположительно в переменной privateKeyBytes (но ваш код неполон, так что я догадываюсь), а затем делаете RSAKeyInfo.Modulus = privateKeyBytes,что странно и криптографически неправдоподобно.Вам также следует создать экземпляр некоторого класса RSA в C #, основываясь на байтах, которые вы читаете, что я и пытаюсь сделать в начале кода C # (первые четыре строки).Я думаю, что для этого должен быть другой API, который просматривает документы:

RSA.ImportParameters(RSAKeyInfo), а затем, возможно, задает RSAKeyInfo из этих байтов, но это не модуль.Чтение в байтах должно быть формата PKCS1 или чего-то подобного, может быть base64, закодированного в файле, или в формате raw и т. Д. Вам нужно посмотреть, какой формат использует Java для экспорта полных ключей на диск.

Вы используете rawбайты, которые вы читаете из файла как модуль, который наверняка создаст проблемы и даст «ключ», который является недопустимым и слишком большим.

...