在节点rsa中使用MD5和MGF1填充的OAEP [英] OAEPwithMD5andMGF1Padding in node-rsa

查看:159
本文介绍了在节点rsa中使用MD5和MGF1填充的OAEP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

下面是我在node.js中的代码.

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);

运行上述代码的结果.

<代码> f1zi49yKJSqkWW2J3Jt2lf1fe79JgqufFawYESOJRqhM4YEcGQBcaP39yptn7vShhsJBCTUOsbiV1YcW/YUzoaSQzX9YU0iTMara7h + LNLUrq4FZ2twy5X3uyAP1sUD1SnvQvlRJqrAh23UAwnx31rv6ySC + XgpLPR7wHYaDbSgyQKiF3qhGRj2SIAZ6weziNPfEm9FifBVjnWMvGDQYbjLbanbnSriN + bWpRtXKH9pQqMoskkiMwCviJdKtKzz/vVr0littPLnw0ojbsGSPKQPS3U3xCH3QiBmxEegc0uy3sJdk6aH/2SMuoPzGu7VS + PsLQctxnvKNnC9qsLFWyA ==真的解密:这是使用RSA加密的字符串!

下面是我在JAVA中的代码

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;
    }


}

下面是运行JAVA代码的结果

Below is the result of running the JAVA code

test
This is the string to be encrypted using RSA!

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

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 ?

推荐答案

OAEP使用的

  • 哈希 Hash ,其八位字节宽度表示为 hLen
  • 公钥的大小, k 个八位位组
  • OAEP使用的掩码生成函数(MGF)
    • the hash Hash used by OAEP, and its width in octet noted hLen
    • the size of the public key, k octets
    • the Mask Generation Function (MGF) used by OAEP

    几乎总是不变的,MGF是

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

    您猜对了,没有指出 Hash Hash'是相同的,或者甚至是 hLen = hLen'.

    You guessed it, there's noting stating that Hash and Hash' are the same, or even that hLen= hLen'.

    而且,相信我,除非对此做了特殊处理,否则在典型的Java环境下"RSA/ECB/OAEPwithMD5andMGF1Padding" (如果支持)将使用MD5作为 Hash ,但对于 Hash',默认为SHA-1;当也许node.js都使用MD5时.

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

    面对SHA-256而不是MD5的类似问题,我们可以强迫漂亮的Java运行时使用正确的方法"

    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
    ));
    

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

    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.

    如果确实需要用Java完成工作,一种选择是将自己的RSAES-OAEP和MD5滚动到通过"RSA/ECB/NoPadding"调用的 Cipher 之上迄今为止,RSA教科书是最复杂的构建块(至少要处理所有密钥管理,模块化算术和卸载到HSM的能力).那是几十行代码,包括MFG1.

    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.

    另一个选项可能是 BouncyCastle .

    即使在MFG1中,继续使用MD5 也是一个坏主意.如果对手在知道消息的一部分之前可以选择消息的一部分,则将其用作主要哈希是不容置疑的灾难.如有疑问,请不要使用MD5 .

    It's a bad idea to keep using MD5, even in MFG1. And it is an unmitigated disaster to use it as the main hash if adversaries can choose a part of the message at a time when they know what's before that part. If in doubt, don't use MD5.

    这篇关于在节点rsa中使用MD5和MGF1填充的OAEP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆