节点-rsa中的OAEPwithMD5和MGF1Padding

时间:2018-03-30 17:42:51

标签: encryption rsa

我试图找出如何在node-rsa中使用OAEPwithMD5和MGF1Padding进行RSA加密。

以下是我在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);

运行上述代码的结果。

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

以下是我在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;
    }


}

以下是运行JAVA代码的结果

test
This is the string to be encrypted using RSA!

但是当我将密码实例从RSA/ECB/OAEPwithSHA1andMGF1Padding更改为"RSA/ECB/OAEPwithMD5andMGF1Padding"(我假设是我在node.js程序的encryptionScheme中提到的那个)时,它会抛出以下错误

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)

有人可以帮我解决问题吗?

1 个答案:

答案 0 :(得分:2)

RSAES-OAEP

参数化
  • OAEP使用的哈希$ \ mathsf {Hash} $,其八位字节宽度为$ \ mathsf {hLen} $
  • 公钥的大小,$ k $ octets
  • OAEP使用的掩码生成功能(MGF)

几乎无一例外,MGF是MFG1,它本身由MFG1使用的散列$ \ underline {\ mathsf {Hash}} $参数化,其宽度以八位字节表示$ \ underline {\ mathsf { hLen}} $(下划线不在标准中,我正在编写这种表示法)。

你猜对了,有人说$ \ mathsf {Hash} $和$ \ underline {\ mathsf {Hash}} $是相同的,甚至是$ \ mathsf {hLen} = \ underline {\ mathsf {为hLen}} $

并且,相信我,除非有一些特别的事情,在典型的Java环境下"RSA/ECB/OAEPwithMD5andMGF1Padding"(如果支持)将使用MD5 for $ \ mathsf {Hash} $但默认为SHA-1 for $ \强调{\ {mathsf哈希}} $;当node.js可能同时使用MD5时。

面对与SHA-256而不是MD5类似的问题,我们可以强制使用优秀的Java运行时来做正确的事情

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

我担心你不会那么幸运,因为MGF1ParameterSpec似乎从未有过MD5说明符;但也许试试new MGF1ParameterSpec("MD5")在放弃之前得到一个。

如果一个人确实需要在Java下完成工作,一个选项就是使用“RSA / ECB / NoPadding”调用Cipher来推送一个带有MD5的RSAES-OAEP,这将执行教科书RSA,到目前为止,最复杂的构建块(至少,所有密钥管理,模块化算法以及卸载到HSM的能力都得到了解决)。这几行代码,包括MFG1。

另一个选项可能是BouncyCastle