Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.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
Java 使用CipherOutputStream的递归加密提供一个空字节[]_Java_Encryption - Fatal编程技术网

Java 使用CipherOutputStream的递归加密提供一个空字节[]

Java 使用CipherOutputStream的递归加密提供一个空字节[],java,encryption,Java,Encryption,我想对字符串加密多次。但我不知道为什么我会以一个空字节数组结束。 一个公钥可以,但添加另一个公钥将返回空结果。。有人知道为什么吗 private static byte[] encrypt(LinkedList<PublicKey> keys, byte[] input) throws Exception { System.out.println("Input length : " + input.length); if (keys.isEmpty()) {

我想对字符串加密多次。但我不知道为什么我会以一个空字节数组结束。 一个公钥可以,但添加另一个公钥将返回空结果。。有人知道为什么吗

private static byte[] encrypt(LinkedList<PublicKey> keys, byte[] input) throws Exception {
    System.out.println("Input length : " + input.length);
    if (keys.isEmpty()) {
        return input;
    }
    PublicKey publicKey = keys.poll();
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    try (CipherOutputStream cipherOutputStream = new CipherOutputStream(byteArrayOutputStream, cipher)) {
        cipherOutputStream.write(input);
    }
    byteArrayOutputStream.flush();
    byteArrayOutputStream.close();
    return encrypt(keys, byteArrayOutputStream.toByteArray());
}

public static void main(String[] args) throws Exception {
    KeyPair pair1 = createPair();
    KeyPair pair2 = createPair();
    LinkedList<PublicKey> keys = new LinkedList<>();
    keys.add(pair1.getPublic());
    keys.add(pair2.getPublic());
    byte[] result = encrypt(keys, "Just testing".getBytes(Charset.forName("UTF-8")));
    System.out.println(new String(result, Charset.forName("UTF-8")));
}

public static KeyPair createPair() throws NoSuchAlgorithmException {
    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
    keyPairGen.initialize(2048);
    return keyPairGen.generateKeyPair();

}
在Topaco的回答之后。。工作版本为:

private static BufferedInputStream encryptS(LinkedList<PublicKey> keys, BufferedInputStream inputStream) throws Exception {
    if (keys.isEmpty()) {
        return inputStream;
    }
    PublicKey publicKey = keys.poll();
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    int currentPos = 0;
    while (inputStream.available() > 0) {
        int sizeToRead = Math.min(inputStream.available(), 245);
        try (CipherOutputStream cipherOutputStream = new CipherOutputStream(byteArrayOutputStream, cipher)) {
            byte[] array = new byte[sizeToRead];
            inputStream.read(array, 0, sizeToRead);
            cipherOutputStream.write(array);
            currentPos += sizeToRead;
        }
    }
    byteArrayOutputStream.close();
    return encryptS(keys, new BufferedInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())));
}
私有静态BufferedInputStream加密(LinkedList密钥,BufferedInputStream inputStream)引发异常{
if(key.isEmpty()){
返回输入流;
}
PublicKey PublicKey=keys.poll();
ByteArrayOutputStream ByteArrayOutputStream=新建ByteArrayOutputStream();
Cipher Cipher=Cipher.getInstance(“RSA/ECB/PKCS1Padding”);
cipher.init(cipher.ENCRYPT_模式,公钥);
int currentPos=0;
while(inputStream.available()>0){
int sizeToRead=Math.min(inputStream.available(),245);
try(CipherOutputStream CipherOutputStream=new CipherOutputStream(byteArrayOutputStream,cipher)){
字节[]数组=新字节[sizeToRead];
读取(数组,0,sizeToRead);
cipherOutputStream.write(数组);
currentPos+=sizeToRead;
}
}
byteArrayOutputStream.close();
返回加密(密钥,新的BufferedInputStream(新的ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
}

对于RSA,必须考虑以下因素:

  • 消息加上填充的长度不得超过键长度(=模数的大小)。填充意味着根据特定的方案向消息中添加额外的字节
  • 密文的长度对应于密钥长度(=模数的大小)
这意味着在第一次加密之后,已达到允许的最大长度。因此,如果没有填充,则不会超过最大长度,如果使用填充,则会超过最大长度

使用创建密码实例

Cipher.getInstance("RSA") 
对应于

Cipher.getInstance("RSA/ECB/PKCS1Padding") 
对于SunJCE提供程序(,),即PKCS1 v1.5 padding与至少11个字符的padding一起使用,因此,密钥大小为256字节时,消息的最大大小不得超过245字节

这就是为什么当前代码中的递归加密不起作用的原因。如果密码实例是使用

Cipher.getInstance("RSA/ECB/NoPadding") 
(未使用填充),当前代码有效


然而,出于安全原因,在实践中必须始终使用填充

关闭密码输出流后关闭字节数组输出流是冗余的,关闭前也是冗余的。不能使用RSA加密任意长度的数据。使用a加密任意长度的数据并保留异步加密的语义。@user207421,特别是因为flush和close都是noop。@BoristeSpider在使用
ByteArrayOutputStream
时没有操作,但我写的总是正确的。
Cipher.getInstance("RSA/ECB/NoPadding")