Estoy tratando de obtener una respuesta cifrada del servidor usando la clave pública RSA. El cifrado se genera en el lado del servidor, pero falla la decodificación en el lado del cliente. Web crypto API arroja una excepción DOM.
servidor Java:
byte[] exponentBytes = Base64.getUrlDecoder().decode(body.exponent); byte[] modulusBytes = Base64.getUrlDecoder().decode(body.modulus); BigInteger exponent = new BigInteger(1, exponentBytes); BigInteger modulus = new BigInteger(1, modulusBytes); RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent); KeyFactory factory = KeyFactory.getInstance("RSA"); PublicKey publicKey = factory.generatePublic(spec); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] cipherBytes = cipher.doFinal("hello".getBytes()) return Base64.getEncoder().encodeToString(cipherBytes);Navegador:
const key = await window.crypto.subtle.generateKey( { name: 'RSA-OAEP', modulusLength: 512, publicExponent: new Uint8Array([1, 0, 1]), hash: 'SHA-256', }, true, ['encrypt', 'decrypt'], ) const jwk = await window.subtle.exportKey('jwk', key.publicKey); const response = await fetch('/foo/bar', { method: 'post', body: { exponent: jwk.e, modulus: jwk.n } }); const body = await response.text(); const binary = window.atob(body); const bytes = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i++) { bytes[i] = binary.charCodeAt(i); } await window.crypto.subtle.decrypt( { name: 'RSA-OAEP' }, key.privateKey, bytes.buffer, ); // returns undefined throws the errorEDITAR: Después de más investigaciones, descubrí que:
En Webcrypto-lado que está utilizando
name: 'RSA-OAEP', hash: 'SHA-256', ...para instanciar el algoritmo. En el lado de Java, "simplemente" crea una instancia del cifrado con
Cipher cipher = Cipher.getInstance("RSA");pero ese es el sinonimo de
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");Debe usar esas líneas para crear una instancia del algoritmo Webcrypto:
Cipher encryptCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); OAEPParameterSpec oaepParameterSpecJCE = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT); encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParameterSpecJCE); ciphertextByte = encryptCipher.doFinal(plaintextByte);Nota de seguridad: una longitud de clave de 512 no es SEGURA , use una longitud de clave mínima de 2048 bits.