【问题标题】:need Help in RSA ENCRYPTION(doFinal)在 RSA ENCRYPTION(doFinal) 中需要帮助
【发布时间】:2012-04-19 03:51:00
【问题描述】:

我正在尝试使用 RSA 算法加密和解密字符串。这里加密工作良好,但问题在于解密。 代码在 DECRYPT 方法中到达 doFinal 时终止。 我输入错误还是公钥和私钥有问题? 请给我有关此的建议。 谢谢你。

public class rsa 
{   
 private KeyPair keypair;       

 public rsa() throws NoSuchAlgorithmException, NoSuchProviderException 
    {
        KeyPairGenerator keygenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
        keygenerator.initialize(1024, random);
        keypair = keygenerator.generateKeyPair();
    }
public String ENCRYPT(String Algorithm, String Data ) throws Exception
{   
    String alg = Algorithm;
    String data=Data;
    byte[] encrypted=new byte[2048];
    if(alg.equals("RSA"))
    {   

        PublicKey publicKey = keypair.getPublic();
        Cipher cipher;
        cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
         encrypted = cipher.doFinal(data.getBytes());
        System.out.println("Encrypted String[RSA] -> " + encrypted);
    }
    return encrypted.toString();
}
public String DECRYPT(String Algorithm, String Data ) throws Exception
{   
    String alg = Algorithm;
    byte[] Decrypted=Data.getBytes();


    if(alg.equals("RSA"))
    {   

        PrivateKey privateKey = keypair.getPrivate();
        Cipher cipher;  
        cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] dec = cipher.doFinal(Decrypted);

        System.out.println("Decrypted String[RSA] -> " + dec.toString());

    }
    return Decrypted.toString();
}
public static void main(String[] args) throws Exception
{
    rsa RSA=new rsa();
    RSA.ENCRYPT("RSA", "avinash");
    RSA.DECRYPT("RSA","[B@cb7e2c");
}

}

 got exception as

Exception in thread "main" javax.crypto.BadPaddingException: Data must start with zero
at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:382)
at javax.crypto.Cipher.doFinal(Cipher.java:2086)
at EncryptionProvider.rsa.DECRYPT(rsa.java:56)
at EncryptionProvider.rsa.main(rsa.java:68)

加密字符串[RSA] -> [B@4a96a

【问题讨论】:

  • 获取异常,因为数据必须从零开始。
  • 请张贴逐字错误信息。
  • 你这里的问题都是Java初学者的问题,和RSA完全没有关系。此外,您还不了解二进制数据作为byte 数组和字符串之间的区别。

标签: java encryption cryptography rsa public-key-encryption


【解决方案1】:

[B@cb7e2c 不是您的加密输出。这是尝试在 byte[] 对象上打印或调用 toString() 的结果。 (比如看System.out.println(new byte[0]);的结果)

尝试将加密后的 byte[] 直接送回解密函数,并使用new String(dec) 打印结果。如果您想以字符串形式查看/保存加密数据,请将其编码为 hex 或 base64。

这就是区别。 byte[] 表示字节数组。它是二进制数据,一系列 8 位有符号数。如果您习惯于仅使用 ascii,则一系列 bytes 和 String 之间的区别可能看起来微不足道,但有很多方法可以用二进制表示字符串。您所做的加密和解密并不关心字符串的外观或数据是否代表字符串;它只是在看位。

如果要加密字符串,则需要将其转换为一系列字节。在另一端,一旦你解密了构成字符串的字节,你就需要将它们转换回来。 myString.getBytes()new String(myBytea) 通常是有效的,但有点草率,因为它们只是使用默认编码。如果 Alice 的系统使用 utf-8 而 Bob 使用 utf-16,那么她的信息对他来说就没有多大意义。因此,最好使用例如myString.getBytes("utf-8")new String(myBytea,"utf-8") 来指定字符编码。

以下是我正在处理的项目中的一些函数,以及 main 函数的演示:

import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.xml.bind.DatatypeConverter;

public class RSAExample {
    private static byte[] h2b(String hex){
        return DatatypeConverter.parseHexBinary(hex);
    }
    private static String b2h(byte[] bytes){
        return DatatypeConverter.printHexBinary(bytes);
    }

    private static SecureRandom sr = new SecureRandom();

    public static KeyPair newKeyPair(int rsabits) throws NoSuchAlgorithmException {
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        generator.initialize(rsabits, sr);
        return generator.generateKeyPair();
    }

    public static byte[] pubKeyToBytes(PublicKey key){
        return key.getEncoded(); // X509 for a public key
    }
    public static byte[] privKeyToBytes(PrivateKey key){
        return key.getEncoded(); // PKCS8 for a private key
    }

    public static PublicKey bytesToPubKey(byte[] bytes) throws InvalidKeySpecException, NoSuchAlgorithmException{
        return KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(bytes));
    }
    public static PrivateKey bytesToPrivKey(byte[] bytes) throws InvalidKeySpecException, NoSuchAlgorithmException{
        return KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(bytes));
    }

    public static byte[] encryptWithPubKey(byte[] input, PublicKey key) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(input);
    }
    public static byte[] decryptWithPrivKey(byte[] input, PrivateKey key) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(input);
    }


    public static void main(String[] args) throws Exception {
        KeyPair kp = newKeyPair(1<<11); // 2048 bit RSA; might take a second to generate keys
        PublicKey pubKey = kp.getPublic();
        PrivateKey privKey = kp.getPrivate();
        String plainText = "Dear Bob,\nWish you were here.\n\t--Alice";
        byte[] cipherText = encryptWithPubKey(plainText.getBytes("UTF-8"),pubKey);
        System.out.println("cipherText: "+b2h(cipherText));
        System.out.println("plainText:");
        System.out.println(new String(decryptWithPrivKey(cipherText,privKey),"UTF-8"));
    }
}

【讨论】:

  • 真的,打印new String(dec) 没有任何意义。如果您真的想查看二进制数据以进行调试,请使用十六进制。如果dec 包含在默认平台编码中未编码为有效字符的字节序列,则String(byte []) 构造函数将跳过它们。这会让新手感到困惑,让他们认为一切都很好。
  • @GregS,你说得对,我应该强调这种区别。查看修改。
  • 非常感谢它在 b2h() 和 h2b() 的对话中帮助了我很多
【解决方案2】:

'[B@4a96a' 不是加密字符串。这是字符串的数据。真正的加密发生在这里

//add this line to your code, it will work fine.
"String encryptedValue = new BASE64Encoder().encode(encrypted);"

现在打印encryptedValue 以查看加密结果。

【讨论】:

  • 所有这些都是已接受答案的前几句话的格式不佳的版本。
  • 在接受的答案中,他没有提到 base 64 编码器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-17
  • 2020-11-16
  • 2014-06-27
  • 2021-05-14
  • 2013-07-17
相关资源
最近更新 更多