Совместимость RSA между C# и Java - PullRequest
1 голос
/ 15 февраля 2020

Я работаю над API, который будет выполнять определенное рукопожатие с агентами [Java, C #], предоставляя им ключевые параметры RSA [Exponent, Modulus, D]. Мне удалось заставить обоих агентов шифровать и дешифровать данные с учетом параметров.

Я пытался проверить совместимость «при наличии одинаковых параметров» между ними. Java агент может беспрепятственно дешифровать C# зашифрованные данные, но я не могу заставить его работать наоборот " для дешифрования java -шифрованных данных с C#"

Вот краткий код для демонстрации проблемы

→ Java ←

RSAParameters. java

class RSAParameters 
{    
    public BigInteger Exponent;
    public BigInteger Modulus;
    public BigInteger P;
    public BigInteger Q;
    public BigInteger DP;
    public BigInteger DQ;
    public BigInteger InverseQ;
    public BigInteger D;

    public RSAParameters(){}

    public RSAParameters(String ExponentString,String ModulusString,String DString)
    {
        this.Exponent = new BigInteger(1, Base64.getDecoder().decode(ExponentString.trim()));
        this.Modulus  = new BigInteger(1, Base64.getDecoder().decode(ModulusString.trim()));
        this.D        = new BigInteger(1, Base64.getDecoder().decode(DString.trim()));
    }

    public RSAParameters(String ExponentString,String ModulusString)
    {
        this.Exponent = new BigInteger(1, Base64.getDecoder().decode(ExponentString.trim()));
        this.Modulus  = new BigInteger(1, Base64.getDecoder().decode(ModulusString.trim()));
    }
}

RSA. java

public class RSA 
{

    public static final RSAParameters HandshakeSharedRSAParameters = new RSAParameters(
            "AQAB",
            "vsn+4HB74ypJ4dqetNWUpKueFAb9V0Vbb1TISWklNa4d1xSmDvF3eZ8bGSciU1PvvPgPVFHh+85ArL/jLqCbMuk8Bx2+y3UJVxXPXpazzv0qPTHd3UXyKeJa/LW+wD+J1Yjy823nT7D8NYOpdt8l9agIO5Me9JiebtxLbljcLMk=",
            "en19YeNV5rbT0Gln03n8gOyeBQWnyUwCNCwemuMivKAZEGl1Y8qrhi4cW73AT/dnx88LKHuZtuzooQBhfyImASGVPXMHYVf4I+f/ZbsYe+ZByyQ/OBlxOYrQxGoDW13us9S+biMyQVQ7MA2TQBmv52e1+LyX7RIsCzxQyUuYFTE="  
    );
    public static String Encrypt(String PlainText,RSAParameters RSAParameters)  throws Exception
    {
        KeyFactory factory = KeyFactory.getInstance("RSA");
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        RSAPublicKeySpec RSAPublicKeySpec = new RSAPublicKeySpec(RSAParameters.Modulus, RSAParameters.Exponent);
        PublicKey PublicKey = factory.generatePublic(RSAPublicKeySpec);
        cipher.init(Cipher.ENCRYPT_MODE, PublicKey);        
        return Base64.getEncoder().encodeToString(cipher.doFinal(PlainText.getBytes()));
    } 
}

Main. java

public class Main
{
    public static void main(String[] args) throws Exception
    {
        String PlainTextToEncrypt = "hello android";
        String Encrypted = RSA.Encrypt(PlainTextToEncrypt,RSA.HandshakeSharedRSAParameters);        
        System.out.println("Encrypted" +":  "+Encrypted);
        //Encrypted changes every execution
        //iDIsNj4QiVWlE8ck48uV0w3tnV5D2ro+3SOMkXan2D4feU6nV5TIVqJGLvMWKvkC+duN9jJzSWTR0CAsK2O2IDx88/9/ycpL0Tk9fumEY2KOINEOXASGxjZvzZ0lCf4AeP9koUp2MHZD8agcYDLe7PLVhA+x8kkAWXMUfyvIS4E=
     }
 }

→ C# ←

RSA.cs

public class RSA
{
    public static readonly RSAParameters HandshakeSharedRSAParameters = new RSAParameters()
    {
        Exponent = Convert.FromBase64String("AQAB"),
        Modulus=Convert.FromBase64String("vsn+4HB74ypJ4dqetNWUpKueFAb9V0Vbb1TISWklNa4d1xSmDvF3eZ8bGSciU1PvvPgPVFHh+85ArL/jLqCbMuk8Bx2+y3UJVxXPXpazzv0qPTHd3UXyKeJa/LW+wD+J1Yjy823nT7D8NYOpdt8l9agIO5Me9JiebtxLbljcLMk="),
        P = Convert.FromBase64String("0l6/pEuwqlpHzjYFb3R9eOa+bQMcidn1h6qKR8DLyDPqA2eCgsBj7fvQvLnl9u6QJMzZdZg8fZP56ZP8nUGG3w=="),
        Q = Convert.FromBase64String("6Cv3YUcsnD1ub6lsqAZaEQrazHtf2HBiIboQlA5sMihThEPyL7Tsc85a8Ln9hFysje6MhNtUF6zyIpAU6NaJVw=="),
        DP = Convert.FromBase64String("zf61jf4H+mf5FDXV0LOzAaaBJWH8mgfx42zdhzGE2n/rUHYVWE9oCuugFI28X7ZvM3ncHsh5w0YZW93raVl25Q=="),
        DQ = Convert.FromBase64String("DsIsuYxSs6PcD1EPzSaKNycffXwiPZn3QvmW8DJygkW5+WBwVsQDe+EUOtU33mAdv+/4EsH2eILP6Y6LJbnthQ=="),
        InverseQ = Convert.FromBase64String("sBvjeZ0HbGT8/JfaPRe8eewHliWp/kpQNLiAGBE2CyFIB0mnkBXa+Vs52niLcMpGI1MLMSmdkDZo2/y+KIFcyg=="),
        D = Convert.FromBase64String("en19YeNV5rbT0Gln03n8gOyeBQWnyUwCNCwemuMivKAZEGl1Y8qrhi4cW73AT/dnx88LKHuZtuzooQBhfyImASGVPXMHYVf4I+f/ZbsYe+ZByyQ/OBlxOYrQxGoDW13us9S+biMyQVQ7MA2TQBmv52e1+LyX7RIsCzxQyUuYFTE=")
    };
    public static String Decrypt(String EncryptedText, RSAParameters RSAParameters)
    {
        RSACryptoServiceProvider CryptoServiceProvider = new RSACryptoServiceProvider();
        CryptoServiceProvider.ImportParameters(RSAParameters);
        return Encoding.Unicode.GetString(CryptoServiceProvider.Decrypt(Convert.FromBase64String(EncryptedText), false));
    }
}

c# демо

String AndroidEncrypted = "iDIsNj4QiVWlE8ck48uV0w3tnV5D2ro+3SOMkXan2D4feU6nV5TIVqJGLvMWKvkC+duN9jJzSWTR0CAsK2O2IDx88/9/ycpL0Tk9fumEY2KOINEOXASGxjZvzZ0lCf4AeP9koUp2MHZD8agcYDLe7PLVhA+x8kkAWXMUfyvIS4E=";
Console.WriteLine(RSA.Decrypt(AndroidEncrypted,RSA.HandshakeSharedRSAParameters));
//Expected -> hello android
//Output -> 敨汬湡牤楯�

1 Ответ

2 голосов
/ 15 февраля 2020

Вы забыли о декодировании символов в C#. Я бы всегда стандартизировал UTF-8. Это набор символов по умолчанию для Android, но не для Windows /. NET - где это UTF-16LE (предполагается, что система с прямым порядком байтов, такая как Windows в Intel или ARM).

В Windows выполните:

Encoding.UTF8.GetBytes(plaintext);

Вам также лучше использовать StandardCharsets.UTF_8 в Android, потому что если бы вы когда-либо использовали это в системе, которая имеет другая кодировка символов (например, Windows, с Windows -1252), тогда ваш код внезапно завершится ошибкой, если вы этого не сделаете.

Поэтому всегда указывайте кодировку символов, например, String#getBytes(StandardCharsets.UTF_8) и new String(byte[] bytes, StandardCharsets.UTF_8).


Обратите внимание, что операция cryptographi c должна быть действительной, если вы вообще получаете какой-либо вывод для RSA , RSA PKCS # 1 всегда проверяет заполнение после дешифрования, и вы ожидаете, что произойдет сбой с исключением, если ключи или схема заполнения неверны.

...