Como portar a chave pública Java RSA para criptografar a função c #?

Aug 29 2020

Deseja usar a chave pública RSA gerada em java, na função c # para criptografar dados e descriptografá-los na função de descriptografia Java.

A chave pública Java gerada foi substituída na tag Modulus em c #:

static string publicKey = "<RSAKeyValue><Modulus>MFwwDQ...wEAAQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

Função de criptografia C #:

  static string Encrypt(string text)
    {
        const int PROVIDER_RSA_FULL = 1;
        const string CONTAINER_NAME = "Tracker";

        CspParameters cspParams;
        cspParams = new CspParameters(PROVIDER_RSA_FULL);
        cspParams.KeyContainerName = CONTAINER_NAME;
       
        RSACryptoServiceProvider rsa1 = new RSACryptoServiceProvider(512,cspParams);
        rsa1.FromXmlString(publicKey);

        byte[] textBytes = Encoding.UTF8.GetBytes(text);
        byte[] encryptedOutput = rsa1.Encrypt(textBytes, RSAEncryptionPadding.Pkcs1);
        string outputB64 = Convert.ToBase64String(encryptedOutput);

        return outputB64;
    }

Função de descriptografia Java:

static String Decrypt(String encodedString,PrivateKey privKey) {
    try {
        Cipher cipher = Cipher.getInstance(cipherInstancename);
        cipher.init(Cipher.DECRYPT_MODE, privKey);
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encodedString));
        return new String(decrypted, "UTF-8");
    } catch (Exception err) {
        return err.fillInStackTrace().toString();
    }
}

Primeira pergunta: É correto substituir a chave pública Java na tag Modulus na string XML c #? E quanto à tag Exponent? Usei o valor AQAB para isso.

A segunda pergunta: por que ao descriptografar em Java, ocorreu este erro:

 javax.crypto.IllegalBlockSizeException: Data must not be longer than 64 bytes

Depois de algumas pesquisas que encontrei, é um erro geral, qual causa pode causar esse tipo de erro?

Respostas

2 Topaco Aug 29 2020 at 17:12

Primeira pergunta: É correto substituir a chave pública Java na tag Modulus na string XML c #?

Não! A chave não é idêntica ao módulo, mas contém o módulo e o expoente. Portanto, no seu caso, ambos devem ser determinados a partir da chave gerada em Java.

Uma chave pública pode ser fornecida em diferentes formatos. Por exemplo, uma chave pública gerada em Java nativo normalmente terá o formato X.509 / SPKI e provavelmente será a byte[], ou seja, na codificação DER. Se o byte[]for codificado em Base64 (corresponde ao postado MFwwDQ...wEAAQ==) e o cabeçalho ----- BEGIN PUBLIC KEY ----- e o rodapé ----- END PUBLIC KEY ----- são adicionados (geralmente no Corpo codificado em Base64 também há uma quebra de linha a cada 64 caracteres), a chave estará na codificação PEM.

A maneira mais fácil de determinar o módulo e o expoente manualmente é carregar a chave PEM em um analisador ASN.1, por exemplo , aqui , ou convertê-la diretamente no formato XML em um site adequado, por exemplo, aqui .

E quanto à tag Exponent? Usei o valor AQAB para isso.

Essa pergunta já foi respondida implicitamente com o que foi dito antes. Mas uma observação: para o expoente, o valor 65537 (codificação hexadecimal 0x010001 e codificação Base64 AQAB ) é freqüentemente escolhido. Mas nem sempre é assim. Portanto, se o expoente de uma chave existente for cegamente substituído por esse valor, há uma grande probabilidade de que funcione, mas você não pode confiar nele, veja, por exemplo, aqui e aqui .

A segunda pergunta: Por que ao descriptografar em Java, ocorreu este erro: javax.crypto.IllegalBlockSizeException: Os dados não devem ser maiores que 64 bytes ?

Isso já foi respondido no comentário de Michael Fehr, entre outros pontos importantes (como segurança, desempenho e criptografia híbrida): O comprimento da chave limita o comprimento do texto simples, com uma chave de 512 bits, no máximo 64 bytes podem ser criptografados.

Além disso, deve-se notar que não apenas o comprimento da chave, mas também o preenchimento usado limita o comprimento do texto simples, por exemplo, PKCS # 1 v1.5 O preenchimento requer 11 bytes, então o comprimento máximo do texto simples para uma chave de 512 bits é 64 - 11 = 53 bytes, aqui . No caso do OAEP, o resumo usado determina quantos bytes o preenchimento requer, consulte, por exemplo, aqui . Se nenhum preenchimento for usado (tetxbook RSA), o comprimento máximo do texto simples corresponde ao comprimento da chave. Na prática, entretanto, o preenchimento deve sempre ser usado por razões de segurança.


A partir do .NET Core 3.0, a importação de uma chave X.509 / SPKI (na codificação DER) e formatos semelhantes são diretamente suportados, veja, por exemplo, aqui e especialmente RSA.ImportSubjectPublicKey. Em versões anteriores do .NET Core e no .NET Framework, essas funções não estão disponíveis, mas BouncyCastle pode ser usado em seu lugar.