OAEPwithMD5andMGF1Padding in node-rsa

孤者浪人 提交于 2019-12-24 12:23:29

问题


I am trying to figure out how to do RSA encryption with OAEPwithMD5andMGF1Padding in node-rsa.

Below is my code in node.js.

    var NodeRSA = require('node-rsa');
    var fs = require('fs');
    var publicKey = '-----BEGIN PUBLIC KEY-----\n*****\n-----END PUBLIC KEY-----';
    var privateKey = '-----BEGIN RSA PRIVATE KEY-----\n*****\n-----END RSA PRIVATE KEY-----'
    const constants = require('constants');
    var options1 = {
      environment: 'node',
      encryptionScheme: {
        scheme: 'pkcs1_oaep',
        hash: 'md5', //hash using for scheme
      }
    }
    var text = 'This is the string to be encrypted using RSA!';
    var encryptKey = new NodeRSA(publicKey, 'pkcs8-public', options1);
    encryptKey.setOptions(options1)

    var encrypted = encryptKey.encrypt(text, 'base64');
    console.log(encrypted);
    console.log(encryptKey.isPublic(true))

    var options2  = {
      environment: 'node',
      encryptionScheme: {
        scheme: 'pkcs1_oaep', //scheme
        hash: 'md5', //hash using for scheme
      }
    }

var decryptKey = new NodeRSA(privateKey, 'pkcs1', options2);
decryptKey.setOptions(options2)
var decrypted = decryptKey.decrypt(encrypted, 'utf8');
console.log('decrypted: ', decrypted);

Result of running the above code.

f1zi49yKJSqkWW2J3Jt2lf1fe79JgqufFawYESOJRqhM4YEcGQBcaP39yptn7vShhsJBCTUOsbiV1YcW/YUzoaSQzX9YU0iTMara7h+LNLUrq4FZ2twy5X3uyAP1sUD1SnvQvlRJqrAh23UAwnx31rv6ySC+XgpLPR7wHYaDbSgyQKiF3qhGRj2SIAZ6weziNPfEm9FifBVjnWMvGDQYbjLbanbnSriN+bWpRtXKH9pQqMoskkiMwCviJdKtKzz/vVr0littPLnw0ojbsGSPKQPS3U3xCH3QiBmxEegc0uy3sJdk6aH/2SMuoPzGu7VS+PsLQctxnvKNnC9qsLFWyA==
true
decrypted:  This is the string to be encrypted using RSA!

Below is my code in JAVA

 import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

import javax.crypto.Cipher;


public class DecryptATT {
    public static void main(String[] args) throws Exception {
        String encryptedData = "f1zi49yKJSqkWW2J3Jt2lf1fe79JgqufFawYESOJRqhM4YEcGQBcaP39yptn7vShhsJBCTUOsbiV1YcW/YUzoaSQzX9YU0iTMara7h+LNLUrq4FZ2twy5X3uyAP1sUD1SnvQvlRJqrAh23UAwnx31rv6ySC+XgpLPR7wHYaDbSgyQKiF3qhGRj2SIAZ6weziNPfEm9FifBVjnWMvGDQYbjLbanbnSriN+bWpRtXKH9pQqMoskkiMwCviJdKtKzz/vVr0littPLnw0ojbsGSPKQPS3U3xCH3QiBmxEegc0uy3sJdk6aH/2SMuoPzGu7VS+PsLQctxnvKNnC9qsLFWyA==";
//      Cipher decrypt = Cipher.getInstance("RSA/ECB/OAEPwithMD5andMGF1Padding");

        Cipher decrypt = Cipher.getInstance("RSA/ECB/OAEPwithSHA1andMGF1Padding");

        RSAPrivateKey privateKey = getPrivateKey();

        System.out.println("test");

        decrypt.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] original = decrypt.doFinal(Base64.getDecoder().decode(encryptedData));

        System.out.println(new String(original));

    }

    public static RSAPrivateKey getPrivateKey() throws Exception {
        String keyPath = "/Users/C.SubbiahVeluAngamuthu/Desktop/Samsung/Docs/att/Keys/3_my_testing/pkcs8_key";
        File privKeyFile = new File(keyPath);
        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(privKeyFile));
        } catch (FileNotFoundException e) {
            throw new Exception("Could not locate keyfile at '" + keyPath + "'", e);
        }
        byte[] privKeyBytes = new byte[(int) privKeyFile.length()];
        bis.read(privKeyBytes);
        bis.close();
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        KeySpec ks = new PKCS8EncodedKeySpec(privKeyBytes);
        RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(ks);
        return privKey;
    }


}

Below is the result of running the JAVA code

test
This is the string to be encrypted using RSA!

But when I change the cipher instance from RSA/ECB/OAEPwithSHA1andMGF1Padding to "RSA/ECB/OAEPwithMD5andMGF1Padding"(which I am assuming is the one that I mentioned in encryptionScheme of node.js program) it throws the below error

test
Exception in thread "main" javax.crypto.BadPaddingException: Decryption error
    at sun.security.rsa.RSAPadding.unpadOAEP(RSAPadding.java:499)
    at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:293)
    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
    at javax.crypto.Cipher.doFinal(Cipher.java:2165)
    at DecryptATT.main(DecryptATT.java:26)

Could some one help me where it is going wrong ?


回答1:


RSAES-OAEP is parametrized by

  • the hash $\mathsf{Hash}$ used by OAEP, and its width in octet noted $\mathsf{hLen}$
  • the size of the public key, $k$ octets
  • the Mask Generation Function (MGF) used by OAEP

Almost invariably, the MGF is MFG1, which itself is parametrized by the hash $\underline{\mathsf{Hash}}$ used by MFG1, and its width in octet noted $\underline{\mathsf{hLen}}$ (the underline is not in the standard, I'm making up this notation).

You guessed it, there's noting stating that $\mathsf{Hash}$ and $\underline{\mathsf{Hash}}$ are the same, or even that $\mathsf{hLen}=\underline{\mathsf{hLen}}$.

And, believe me, unless something special is done about it, under a typical Java environement "RSA/ECB/OAEPwithMD5andMGF1Padding" (if supported) will use MD5 for $\mathsf{Hash}$ but default to SHA-1 for $\underline{\mathsf{Hash}}$; when perhaps node.js uses MD5 for both.

Facing a similar problem with SHA-256 rather than MD5, we can coerce the nice Java runtime to do the Right Thing with

Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, privKey, new OAEPParameterSpec(
    "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT
));

I fear you won't be so lucky, since MGF1ParameterSpec seems to never have had an MD5 specifier; but perhaps give a try to new MGF1ParameterSpec("MD5") to get one before giving up.

If one really needs to get the job done under Java, one option is to roll one's RSAES-OAEP with MD5 on top of Cipher invoked with "RSA/ECB/NoPadding", which will perform textbook RSA, by far the most complex building block (at least, all the key management, modular arithmetic, and ability to offload to an HSM is taken care of). That's few dozens lines of code, including MFG1.

Another option might be BouncyCastle.



来源:https://stackoverflow.com/questions/49583427/oaepwithmd5andmgf1padding-in-node-rsa

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!