简体   繁体   中英

Java cipherinputstream turns all input data to 0

I am writing an implementation of an algorithm for public and private key encryption using an RSA cipher and an AES cipher. In this method, the AES key is supposed to be deciphered by using an RSA CipherInputStream.

public void loadKey(File in, byte[] privateKey) throws GeneralSecurityException, IOException {

    PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKey);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PrivateKey pk = kf.generatePrivate(privateKeySpec);
    rsacipher.init(Cipher.DECRYPT_MODE, pk);

    aesKey = new byte[128/8];
    FileInputStream fis = new FileInputStream(in);
    CipherInputStream input = new CipherInputStream(fis, rsacipher);
    input.read(aesKey);
    aesKeySpec = new SecretKeySpec(aesKey, "AES");
    input.close();
    fis.close();
 } 

the FileInputStream gives me the encoded key (it is not the problem) but when passed through the CipherInputStream, the data becomes all zeroes.

aesKey and aesKeySpec are static variables, privateKey is a valid RSA key.

Any help in finding the problem would be much appreciated!

Looking at the source, CipherInputStream does a great job of eating exceptions thrown by the crypto layer. I would avoid its use entirely in favour of a simple Cipher object, eg

byte[] fileData = FileUtils.readFileToByteArray(in); // from commons-lang
Cipher c = new Cipher("RSA/None/PKCS1Padding");
c.init(Cipher.DECRYPT_MODE, pk);
aesKey = c.doFinal(fileData);
// etc.

You are ignoring the return value of the InputStream.read(byte[]) method:

input.read(aesKey);

This call is not guaranteed to read the number of bytes equal to the length of the passed byte array in one go. You should use a cycle and repeatedly read from the input stream into the remaining part of the array:

int offset = 0;
while (offset < aesKey.length) {
    int read = input.read( aesKey, offset, aesKey.length - offset );
    if (read < 0) {
         throw new EOFException();
    } else {
         offset += read;
    }
}

Or you can wrap the stream into DataInputStream and use DataInputStream.readFully(byte[]) method (which essentially contains the same code as above).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM