提问者:小点点

使用nodeJS和Objective-C的非对称公钥/私钥加密RSA


我想使用非对称加密(RSA)加密我的服务器(用nodeJS编写)和iOS应用程序(用Objective-C编写)之间的通信。

我想做的是只加密我从iOS应用程序(使用公钥)发送到服务器的数据,服务器需要解密数据(使用私钥)才能读取它。

使用GitHub中的以下库,出于测试目的,我能够成功加密然后解密字符串“hello world!”使用Objective-C。注意:NSString*encWellPubKey是加密的base64字符串

>

  • https://github.com/ideawu/Objective-C-RSA

    NSString *pubkey = @"-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI2bvVLVYrb4B0raZgFP60VXY\ncvRmk9q56QiTmEm9HXlSPq1zyhyPQHGti5FokYJMzNcKm0bwL1q6ioJuD4EFI56D\na+70XdRz1CjQPQE3yXrXXVvOsmq9LsdxTFWsVBTehdCmrapKZVVx6PKl7myh0cfX\nQmyveT/eqyZK1gYjvQIDAQAB\n-----END PUBLIC KEY-----";
    NSString *privkey = @"-----BEGIN PRIVATE KEY-----\nMIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMMjZu9UtVitvgHS\ntpmAU/rRVdhy9GaT2rnpCJOYSb0deVI+rXPKHI9Aca2LkWiRgkzM1wqbRvAvWrqK\ngm4PgQUjnoNr7vRd1HPUKNA9ATfJetddW86yar0ux3FMVaxUFN6F0KatqkplVXHo\n8qXubKHRx9dCbK95P96rJkrWBiO9AgMBAAECgYBO1UKEdYg9pxMX0XSLVtiWf3Na\n2jX6Ksk2Sfp5BhDkIcAdhcy09nXLOZGzNqsrv30QYcCOPGTQK5FPwx0mMYVBRAdo\nOLYp7NzxW/File//169O3ZFpkZ7MF0I2oQcNGTpMCUpaY6xMmxqN22INgi8SHp3w\nVU+2bRMLDXEc/MOmAQJBAP+Sv6JdkrY+7WGuQN5O5PjsB15lOGcr4vcfz4vAQ/uy\nEGYZh6IO2Eu0lW6sw2x6uRg0c6hMiFEJcO89qlH/B10CQQDDdtGrzXWVG457vA27\nkpduDpM6BQWTX6wYV9zRlcYYMFHwAQkE0BTvIYde2il6DKGyzokgI6zQyhgtRJ1x\nL6fhAkB9NvvW4/uWeLw7CHHVuVersZBmqjb5LWJU62v3L2rfbT1lmIqAVr+YT9CK\n2fAhPPtkpYYo5d4/vd1sCY1iAQ4tAkEAm2yPrJzjMn2G/ry57rzRzKGqUChOFrGs\nlm7HF6CQtAs4HC+2jC0peDyg97th37rLmPLB9txnPl50ewpkZuwOAQJBAM/eJnFw\nF5QAcL4CYDbfBKocx82VX/pFXng50T7FODiWbbL4UnxICE0UBFInNNiWJxNEb6jL\n5xd0pcy9O2DOeso=\n-----END PRIVATE KEY-----";
    
    NSString *originString = @"hello world!";
    
    // Demo: encrypt with public key
    NSString *encWithPubKey = [RSA encryptString:originString publicKey:pubkey];
    NSLog(@"Enctypted with public key: %@", encWithPubKey);// prints the encrypted string in base64 format
    
    
    // Demo: decrypt with private key
    NSString *decWithPrivKey = [RSA decryptString:encWithPubKey privateKey:privkey];
    NSLog(@"Decrypted with private key: %@", decWithPrivKey);// prints -> hello world!
    

    使用以下链接,出于测试目的,我还能够加密然后解密字符串“hello world!”使用nodeJs:

    >

  • https://coolaj86.com/articles/asymmetric-public--private-key-encryption-in-node-js

    var fs = require('fs');
    var ursa = require('/PATH/ursa');
    
    var pubkeyAlice = ursa.createPublicKey(fs.readFileSync("/PATH/public.pem"));
    var privkeyAlice = ursa.createPrivateKey(fs.readFileSync("/PATH/private.pem"));
    
    var msg = "hello world!";
    var enc = pubkeyAlice.encrypt(msg, 'utf8', 'base64');
    console.log('encrypted string:'+enc);
    
    var rcv = privkeyAlice.decrypt(enc, 'base64', 'utf8');
    console.log('decrypted', rcv, '\n');
    

    以下两个示例都成功打印了“hello world!”。接下来,我从Objective-C(base64格式)中获取了加密字符串NSString*encWellPubKey,然后我尝试使用nodeJS解密它:

        var privkeyAlice = ursa.createPrivateKey(fs.readFileSync("/PATH/private.pem"));
    
        var enc = <  HERE IS THE ENCRYPTED STRING RECEIVED FROM Objective-C : encWithPubKey  >
        var rcv = privkeyAlice.decrypt(enc, 'base64', 'utf8');
        console.log('decrypted', rcv, '\n');
    

    但是,这样做时,我在nodeJS中收到以下错误:

    • 错误:错误:040A1079:rsa例程:RSA_padding_check_PKCS1_OAEP_mgf1:oaep解码错误

    根据我的理解,这个错误意味着加密的字符串无效。然而,我无法理解为什么我会得到这个错误。如果我用相同的语言进行加密和解密,我可以加密和解密相同的字符串,但是,我无法在两种语言之间进行通信。

    请注意,iOS应用程序和nodeJS分别使用以下公钥和私钥:

    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI2bvVLVYrb4B0raZgFP60VXY
    cvRmk9q56QiTmEm9HXlSPq1zyhyPQHGti5FokYJMzNcKm0bwL1q6ioJuD4EFI56D
    a+70XdRz1CjQPQE3yXrXXVvOsmq9LsdxTFWsVBTehdCmrapKZVVx6PKl7myh0cfX
    QmyveT/eqyZK1gYjvQIDAQAB
    -----END PUBLIC KEY-----
    
    
    -----BEGIN PRIVATE KEY-----
    MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMMjZu9UtVitvgHS
    tpmAU/rRVdhy9GaT2rnpCJOYSb0deVI+rXPKHI9Aca2LkWiRgkzM1wqbRvAvWrqK
    gm4PgQUjnoNr7vRd1HPUKNA9ATfJetddW86yar0ux3FMVaxUFN6F0KatqkplVXHo
    8qXubKHRx9dCbK95P96rJkrWBiO9AgMBAAECgYBO1UKEdYg9pxMX0XSLVtiWf3Na
    2jX6Ksk2Sfp5BhDkIcAdhcy09nXLOZGzNqsrv30QYcCOPGTQK5FPwx0mMYVBRAdo
    OLYp7NzxW/File//169O3ZFpkZ7MF0I2oQcNGTpMCUpaY6xMmxqN22INgi8SHp3w
    VU+2bRMLDXEc/MOmAQJBAP+Sv6JdkrY+7WGuQN5O5PjsB15lOGcr4vcfz4vAQ/uy
    EGYZh6IO2Eu0lW6sw2x6uRg0c6hMiFEJcO89qlH/B10CQQDDdtGrzXWVG457vA27
    kpduDpM6BQWTX6wYV9zRlcYYMFHwAQkE0BTvIYde2il6DKGyzokgI6zQyhgtRJ1x
    L6fhAkB9NvvW4/uWeLw7CHHVuVersZBmqjb5LWJU62v3L2rfbT1lmIqAVr+YT9CK
    2fAhPPtkpYYo5d4/vd1sCY1iAQ4tAkEAm2yPrJzjMn2G/ry57rzRzKGqUChOFrGs
    lm7HF6CQtAs4HC+2jC0peDyg97th37rLmPLB9txnPl50ewpkZuwOAQJBAM/eJnFw
    F5QAcL4CYDbfBKocx82VX/pFXng50T7FODiWbbL4UnxICE0UBFInNNiWJxNEb6jL
    5xd0pcy9O2DOeso=
    -----END PRIVATE KEY-----
    

    我尝试在网上寻找,但我无法找到足够的资源来解决这个问题。任何帮助都将不胜感激!谢谢!


  • 共2个答案

    匿名用户

    不要。加密两个系统之间通信的正确解决方案是使用TLS。尝试自己实施加密几乎肯定不会有好结果,最终会导致你的密码被破解——很难安全地实施加密,以至于即使是有经验的密码学家也尽可能避免加密。

    在IRC上与作者进一步讨论了这个问题,并确定反对使用TLS的理由是“客户端可以加载自定义CA并使用类似Burp的东西拦截请求”:

    阻止客户端修改是不可能的。客户端从根本上是不受信任的,确保客户端不会篡改请求在技术上是不可能的。相反,请求的验证应该发生在服务器端,这样客户端做什么样的篡改就无关紧要了。本文将详细介绍。

    匿名用户

    感谢好奇程序员,我从这个链接中找到了答案:

    • 尝试使用私钥解密消息时node-rsa错误

    我现在需要node-rsa而不仅仅是rsa。我修复我的代码的行是这样的:

        myDecrypter.setOptions({encryptionScheme: 'pkcs1'});
    

    其中myDecry人是私钥。