Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
RSA加密:在android/java中加密,在python中解密(加密) 问题_Java_Android_Python_Encryption_Rsa - Fatal编程技术网

RSA加密:在android/java中加密,在python中解密(加密) 问题

RSA加密:在android/java中加密,在python中解密(加密) 问题,java,android,python,encryption,rsa,Java,Android,Python,Encryption,Rsa,我正在尝试在python和java/android之间配置非对称加密。用例是安全地存储用户密码(使用公钥),允许对服务器(具有私钥)进行重新身份验证 我已经在Python和Java中分别使用了加密算法,但无法让我的Python端对Java生成的密文进行解密。我认为两个最可能的问题是 base64编码字符串的问题(一直在努力解决这些问题!),或者 客户端/服务器之间的填充和其他加密规范不匹配 为了在这里创建一个完整的示例,我将复制私钥和公钥,然后重新生成一个新的集以供实际使用 Java(客户端)代

我正在尝试在python和java/android之间配置非对称加密。用例是安全地存储用户密码(使用公钥),允许对服务器(具有私钥)进行重新身份验证

我已经在Python和Java中分别使用了加密算法,但无法让我的Python端对Java生成的密文进行解密。我认为两个最可能的问题是

  • base64编码字符串的问题(一直在努力解决这些问题!),或者
  • 客户端/服务器之间的填充和其他加密规范不匹配
  • 为了在这里创建一个完整的示例,我将复制私钥和公钥,然后重新生成一个新的集以供实际使用

    Java(客户端)代码: Java导入

    // Java imports
    import android.util.Base64;
    import android.util.Log;
    import java.security.KeyFactory;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.spec.MGF1ParameterSpec;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import javax.crypto.Cipher;
    import javax.crypto.spec.OAEPParameterSpec;
    import javax.crypto.spec.PSource;
    
    from cryptography.hazmat.primitives import serialization, hashes
    from cryptography.hazmat.primitives.asymmetric import rsa, padding
    from cryptography.hazmat.backends import default_backendb
    
    Java加密代码-我为代码格式/宽度道歉

    public class RSAEncryption {
    
        public void encrypt (String ... strings) throws Exception {
    
            // Load in public key, remove escape characters, headers, footers:     
            String public_key_string = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6kTFJl+6jG2rfYlZxtFi\nzajOgvKgInJHOa4i3G5vB9c7f7kzsTMOmeg5YHn3LNndg4Wx4AyfN5fbcNGg+KmJ\nK91b2lkgFy7pVEhWfzK4/yqk0liG7MwuN0G8GqUjIqJOXPS6lXB9Zr3n9QyTkKGV\n9cnNVPV1CNuN3bOu0t8Mu3fvZ+z8edq/cfUpTXwDdfRmZ6WeWxxqogK2uCwmneEN\n8kqyWE4OxhyqLJMw9mCGHOqTVgJUnvjMBezywr6s3vIcs2Q7CnxQx/g/GTqhUxLS\nHDlyAFDbhU4BWkCHrCa/nTyIFgXC9X4YRpQd24xfGXJjB2qUVv2H0O5FoRJAEYvS\nfQIDAQAB\n-----END PUBLIC KEY-----\n";
    
            String publicKeyContent = public_key_string.replaceAll("\\n", "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");
    
            // Encrypt input using OAEP / SHA-256 /MGF1
            byte[] input = strings[0].getBytes();
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPwithSHA-256andMGF1Padding");
    
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    
            byte[] publicBytes = Base64.decode(publicKeyContent, Base64.DEFAULT);
            X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(publicBytes);
            PublicKey pubKey = keyFactory.generatePublic(keySpecX509);
            cipher.init(Cipher.ENCRYPT_MODE, pubKey, new OAEPParameterSpec("SHA-256",
                    "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT));
            byte[] cipherText = cipher.doFinal(input);
    
            return cipherText;
    
        }
    
    }
    
    如果我使用输入字符串=“test text”运行这些代码,我将获得以下加密输出:

    BoOymgUGnB/LIqYOhBmW60HCL4s6FQFlNpRmhqm63AGq7gud4g96og6f+5yHUVHktAT0pl93UpAz//aae4esTseR6/o7jD/NGS+gZlNRHsSuNNstVZ8wOp1S03YcHYEpXtTdElMiKso4cbZmO20SoUvyzjI5e7RM1aWKCebqCvG7RYneCgoMi611AY2cVSwMYOENcRwqXeB3sFMrjoNQ1TkkgHU5MSxDbVLbNO72AYYQi/TkwiQ57qnjgk3KHXeatJv/5hWqa5ooBCy6aLDFux6X2721wTVa2/RSiZKG7DJHObV5pQNw4zjGWc4d5IJ+P/o6GKHY4fTj8ujqS6A44Q==
    
    我相信这是可行的,因为我可以用私钥(用另一个代码块,这里不复制)成功地解密它

    然后将其用作python代码的输入

    Python(服务器端)代码 Python导入

    // Java imports
    import android.util.Base64;
    import android.util.Log;
    import java.security.KeyFactory;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.spec.MGF1ParameterSpec;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import javax.crypto.Cipher;
    import javax.crypto.spec.OAEPParameterSpec;
    import javax.crypto.spec.PSource;
    
    from cryptography.hazmat.primitives import serialization, hashes
    from cryptography.hazmat.primitives.asymmetric import rsa, padding
    from cryptography.hazmat.backends import default_backendb
    
    Python解密代码

    PRIVATE_KEY_STRING='-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDqRMUmX7qMbat9\niVnG0WLNqM6C8qAickc5riLcbm8H1zt/uTOxMw6Z6Dlgefcs2d2DhbHgDJ83l9tw\n0aD4qYkr3VvaWSAXLulUSFZ/Mrj/KqTSWIbszC43QbwapSMiok5c9LqVcH1mvef1\nDJOQoZX1yc1U9XUI243ds67S3wy7d+9n7Px52r9x9SlNfAN19GZnpZ5bHGqiAra4\nLCad4Q3ySrJYTg7GHKoskzD2YIYc6pNWAlSe+MwF7PLCvqze8hyzZDsKfFDH+D8Z\nOqFTEtIcOXIAUNuFTgFaQIesJr+dPIgWBcL1fhhGlB3bjF8ZcmMHapRW/YfQ7kWh\nEkARi9J9AgMBAAECggEARuUi6JcFxGOYBzies51AEk7omBZGwcXlqh35rM26yhun\nhOKOMyzpWUg+vOSMGcWg1KGMD+qh8FgDb6Pw2++qdFzb5DsejAWFVR1DF+FIvOex\n03o48sZjohNBkqqw9FU788OYB4twV7xWywDQU2+jCyvT+McDcPfIefRbjrMzjjOM\nOhMY0F6OXeDpuZttgqZsP65aA7yaIfjuk5tuYbpZvNmV1DAlqfGmxt2PO1laobGQ\nS7Vx18zpWWdh/GgnbZDD3SG69AmAWIdOZNV6SuUC5lgOqw2O+8TB7MXFbiCy7v5J\n1tMap6OCRDm5jLsc6ZFP5Zs1s9/FnW9/jCxw4kFxPQKBgQD7DcVUaW7rKUmYORAA\nqY6uAIu+Lo+607G4Nva52Rotj0vdiIsAYxJPP2dxKTjL0GLbKIsOcmd2xD0e1/yu\nlAu6koCyC5cT5XwNJ388XDwtWPU2J7mC1TKq0TJUZ56uzdZxNKOWQ7Upq3901zbQ\nQhssjJpgX09CPzlfpAc9NHhchwKBgQDu4lc5HaJNsFeEMOuaUmTUu+W+veIZZaV3\n7yTnLxoJCyqu5DVKvhMwDZP3I2JuvHbCPf3AzshvNcbCiG/6u9CQSbv4wRZO6p8c\nlIAymy0neaq7+uxHdvem58A4xIlKhlnNpzIqE9fay7ejAklGPTFs/YdsyVXwADVr\n30cfOdO92wKBgCCrGhJx5c0UAk+cnUh4x+g8ifKlfG6DPY0LGe/1IELtcqHRMsVK\nHwfQ6FUBWDKtWy/Jhs7KdEwwHQP2dxsAiMYuajDA8VfVdN8BVL02A16jRMVXRfyQ\nYZd4wWPaV/vHLTBt+RuEk/5oIp3Bo5BWCdMyOKRxwo6MS5r2bTq5qS/hAoGAKezT\nfhSzXYsrcOndD7KSO7vWcImG2wo55ji0c1aS7S9miFdI+xss5uwbIe614dV1ylVy\n6ZnhF5OKlK25aXn4+rnWIaxRq/wFfNCbR0ZwwFLcIi3BtjEs+cAGvm/P4KJ/tFY5\nuaTN53qFejh2f7tRp10/nVogmQSQW6ROKS7O+K0CgYA03s/ajxaYTLzBHpIdqisl\nsGaen4IBibB3OZs/vplBZ0xG34B8+MC8qgvC6DFVR4Y3XMol8lOGiS6OQVvIRjnC\nhqd/QobpH0j5Wy2cM+6yXVvj95dwif7QjaqDydniRhGbxa6iJ8vTYqyl9yNjWwX/\n72JRzDNB+9De2LntVwzBwA==\n-----END PRIVATE KEY-----\n'
    
    #Load the java output into a bytes object to decrypt
    java_out = b'BoOymgUGnB/LIqYOhBmW60HCL4s6FQFlNpRmhqm63AGq7gud4g96og6f+5yHUVHktAT0pl93UpAz//aae4esTseR6/o7jD/NGS+gZlNRHsSuNNstVZ8wOp1S03YcHYEpXtTdElMiKso4cbZmO20SoUvyzjI5e7RM1aWKCebqCvG7RYneCgoMi611AY2cVSwMYOENcRwqXeB3sFMrjoNQ1TkkgHU5MSxDbVLbNO72AYYQi/TkwiQ57qnjgk3KHXeatJv/5hWqa5ooBCy6aLDFux6X2721wTVa2/RSiZKG7DJHObV5pQNw4zjGWc4d5IJ+P/o6GKHY4fTj8ujqS6A44Q=='
    
    #Load the private key string into a functioning key object
    private_key = serialization.load_pem_private_key(
             PRIVATE_KEY_STRING.encode('UTF-8'),
             password=None,
             backend=default_backend()
             )
    
    #Decrypt the input
    private_key.decrypt(
        java_out,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    
    使用相同的代码(以及另一个要加密的块),我可以在Python中成功地加密/解密。但是,当使用Java的输出作为输入时,此代码返回以下错误:

    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-71-9af0738427f1> in <module>()
          4         mgf=padding.MGF1(algorithm=hashes.SHA256()),
          5         algorithm=hashes.SHA256(),
    ----> 6         label=None
          7     )
          8 )
    
    C:\ProgramData\OWTools\miniconda\lib\site-packages\cryptography\hazmat\backends\openssl\rsa.py in decrypt(self, ciphertext, padding)
        384         key_size_bytes = int(math.ceil(self.key_size / 8.0))
        385         if key_size_bytes != len(ciphertext):
    --> 386             raise ValueError("Ciphertext length must be equal to key size.")
        387 
        388         return _enc_dec_rsa(self._backend, self, ciphertext, padding)
    
    ValueError: Ciphertext length must be equal to key size.
    
    这显然与java输出完全不同——尽管我不完全确定原因(或者这意味着什么!)


    非常感谢任何帮助!感谢

    根据Kelakela的评论,我意识到问题在于Java代码的输出是Base64,而python代码需要二进制输入

    解决方案非常简单:

    from codecs import decode 
    ciphertext = base64.decode(java_out, 'base64')
    
    然后以二进制格式对输出运行
    私钥.解密(密文…)


    代码的其余部分对我来说很好。

    嗨,凯拉拉卡。你是对的,问题在于二进制和base64格式之间的差异——这不是我以前遇到过的。现在已经修复了,使用ciphertext=base64.decode(java_out,'base64')为Python代码创建新的输入。谢谢大家!@kelalaka您应该明确指出您所指的“消息”是纯文本加上填充。@kelalaka那么您的评论是误导性的,因为消息加上填充必须小于模数(不仅仅是消息)。@Kelalalaka-已经添加了一个答案来解释我所做的。再次感谢你。