4

我正在做一个简单的程序来使用 Java 中的 RSA 算法进行加密/解密。我创建了一个密码对象,如下所示:

//Create a Cipher object
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/NoPadding");

我通过调用 encrypt 函数进行加密:

String cipher=encrypt(textByte, pair, rsaCipher);
System.out.println("The Encryption using RSA Algorithm : "+cipher);

并且解密为:

//Decryption
String plain=decrypt(Base64.decodeBase64(cipher),pair, rsaCipher);
System.out.println("The Decryption using RSA Algorithm : "+plain);

当我显示输出时,解密输出在原始文本前返回一个长空格: 在此处输入图像描述

但是,当我将用于创建 Cipher 对象的代码编辑为: //Create a Cipher object Cipher rsaCipher = Cipher.getInstance("RSA");

即,删除操作模式和填充参数,问题得到解决,输出变为: 在此处输入图像描述

问题出在哪里。在第一种情况下(出现空格时),我指定了 NoPadding? 为什么空格会出现在解密的消息中?即使我使用了填充,我希望这不应该发生。

编辑: 这是加密和解密方法:

public static String encrypt(byte[] textBytes, KeyPair pair, Cipher rsaCipher) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
    //get the public key
    PublicKey pk=pair.getPublic(); 


    //Initialize the cipher for encryption. Use the public key.
    rsaCipher.init(Cipher.ENCRYPT_MODE, pk);

    //Perform the encryption using doFinal
    byte[] encByte = rsaCipher.doFinal(textBytes);

    // converts to base64 for easier display.
    byte[] base64Cipher = Base64.encodeBase64(encByte);

    return new String(base64Cipher);
}//end encrypt

public static String decrypt(byte[] cipherBytes, KeyPair pair, Cipher rsaCipher) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException
{
    //get the public key
    PrivateKey pvk=pair.getPrivate(); 

    //Create a Cipher object
    //Cipher rsaCipher = Cipher.getInstance("RSA/ECB/NoPadding");

    //Initialize the cipher for encryption. Use the public key.
    rsaCipher.init(Cipher.DECRYPT_MODE, pvk);

    //Perform the encryption using doFinal
    byte[] decByte = rsaCipher.doFinal(cipherBytes);

    return new String(decByte);

}//end decrypt
4

2 回答 2

5

您的问题确实与填充有关。安全 RSA 功能需要某种填充,无论是 PKCS#1 1.5 还是实践中的 OAEP 填充。此外,需要找到加密的纯文本的开始和结束。

RSA 的模幂运算是使用大整数执行的。然后将这些操作的结果表示为八位字节字符串。这些八位字节字符串基本上是整数的大端、无符号、固定长度表示。这些整数用00有价值的字节填充(这在 RSA 标准中称为 I2OS 原语)。所以你看到的是模幂运算的结果,00填充仍然存在。

长话短说,始终使用填充方案。如今,OAEP 将更可取。将其与混合加密方案一起使用,或使用更高级别的容器格式,例如 CMS 或 PGP。

于 2013-10-28T00:24:24.680 回答
0
//This is a complete encryption and decryption module using 
//Algorithm: JWEAlgorithm.RSA_OAEP_256
//Encryption Method: A128CBC_HS256

public static String  encrypt(String text) throws Exception {
    // Set the plain text
    Payload payload = new Payload(text);
    // Create the header
    JWEHeader header = new JWEHeader(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A128CBC_HS256);
    // Create the JWE object and encrypt it
    JWEObject jweObject = new JWEObject(header, payload);
    jweObject.encrypt(new RSAEncrypter(getPublicKey()));
    // Serialise to compact JOSE form...
    String jweString = jweObject.serialize();
    LOG.info("Generated Encrypted Key : {}", jweString);
    return jweString;
}

public static String decrypt(String text) throws Exception {
    // Parse into JWE object...
    JWEObject jweObject = JWEObject.parse(text);
    jweObject.decrypt(new RSADecrypter(getPrivateKey()));
    // Get the plain text
    Payload payload = jweObject.getPayload();
    System.out.println(payload.toString());
    return payload.toString();
}

private static RSAPublicKey getPublicKey() throws Exception {
    String filename = "/home/vaibhav/Setups/cert/pub.der";
    File f = new File(filename);
    FileInputStream fis = new FileInputStream(f);
    DataInputStream dis = new DataInputStream(fis);
    byte[] keyBytes = new byte[(int)f.length()];
    dis.readFully(keyBytes);
    dis.close();

    X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return (RSAPublicKey) kf.generatePublic(spec);
}

private static RSAPrivateKey getPrivateKey() throws Exception {
    String filename = "/home/vaibhav/Setups/cert/private.pkcs8";
    File f = new File(filename);
    FileInputStream fis = new FileInputStream(f);
    DataInputStream dis = new DataInputStream(fis);
    byte[] keyBytes = new byte[(int)f.length()];
    dis.readFully(keyBytes);
    dis.close();

    PKCS8EncodedKeySpec spec1 = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return (RSAPrivateKey) kf.generatePrivate(spec1);
}
于 2018-05-21T10:46:13.280 回答