如何使用 node-rsa 加密 node.js 中的数据并解密 android 中的加密数据?

How to encrypt data in node.js using node-rsa and decrypt encrypted data in android?

Node.js 加密代码

   function encrypt(msg) {
        try {
            const public_key = fs.readFileSync(path.join(__dirname, 'PublicKey.pem'), 'utf8');
            const encryptStr = crypto.publicEncrypt({
                key: public_key,
                padding: crypto.constants.RSA_PKCS1_PADDING
            }, Buffer.from(msg,'utf8'));
            let encryptString = encryptStr.toString('hex');
            return encryptString;
        } catch (e) {
            console.log(e);
            return false;
        }
    }

Android解密代码

  public static String decryptStringWithPrivateKey(String s, String keyFilename)  throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        PrivateKey pkey = readPrivateKeyFromPem(keyFilename);

        cipher.init(Cipher.DECRYPT_MODE, pkey);
        String dec = new String(cipher.doFinal(Base64.getDecoder().decode(s)), "UTF-8");

        return dec;
    }


   public static PrivateKey readPrivateKeyFromPem(String keyFilename) throws Exception {
        byte[] keyBytes = Files.readAllBytes(new File(keyFilename).toPath());
        String keyString = new String(keyBytes);

        if (keyString.contains("BEGIN PRIVATE KEY")) {
            return readPrivateKeyFromPem_PKCS8(keyFilename);
        }
        else if(keyString.contains("BEGIN RSA PRIVATE KEY")){
            return readPrivateKeyFromPem_PKCS1(keyFilename);
        }
     
        throw new Exception("Unknown private key format in "+keyFilename);
    }

我想在服务器端加密 api 并在 android 设备上解密数据以避免未经授权的访问。

在 android 上解密时“输入字节数组在 172 处的结束字节不正确” 抛出这一错误。

在 NodeJS 代码中,密文是十六进制编码的,在 Java 代码中,它是 Base64 解码的。这个一定要保持一致,两边不是Base64就是十六进制编码。

此外,在Java代码中,在实例化密码时,只指定了算法。这导致使用默认填充,例如在我的机器上(API 28,Android 9 Pie)对应于 RSA/ECB/NoPadding。这与使用 PKCS#1 v1.5 填充的 NodeJS 端不兼容(除了没有填充的 RSA,所谓的教科书 RSA 是不安全的)。因此,还必须在密码实例化中指定填充 RSA/ECB/PKCS1Padding.

使用 PKCS#8 格式的私钥和 readPrivateKeyFromPem_PKCS8() 自己的实现,如果上述两个错误得到修复,这两种代码都可以在我的机器上运行。但是,未发布的方法也可能存在缺陷。