有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

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();

}

输出是

Input length : 12
Input length : 256
Input length : 0

在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())));
}

共 (1) 个答案

  1. # 1 楼答案

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

    • 消息加上填充的长度不得超过键长度(=模的大小)[^{}][^{}][^{}][^{}]。填充意味着根据某个方案[^{}]向消息添加额外的字节
    • 密文的长度对应于密钥长度(=模的大小),[^{}]

    这意味着在第一次加密之后,已达到允许的最大长度。因此,如果没有填充,则不会超过最大长度,如果使用填充,则会超过最大长度

    使用创建密码实例

    Cipher.getInstance("RSA") 
    

    对应于

    Cipher.getInstance("RSA/ECB/PKCS1Padding") 
    

    对于SunJCE提供程序([^{}][^{}]),即PKCS1 v1。5填充与至少11个字符的填充一起使用,因此,当密钥大小为256字节时,消息的最大大小不得超过245字节

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

    Cipher.getInstance("RSA/ECB/NoPadding") 
    

    (未使用填充),当前代码有效

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