问题描述
CipherInputStream和CipherOutputStream可以当做具有加/解密功能的包装器使用。但是,如果读取文件时在把输入流用两个(或以上)CipherInputStream包装,将明文字节加密成密文字节,再将此密文字节存盘;然后,将密文字节读入,再把输出流用两个(或以上)CipherOutputStream包装,然后将得到的明文字节写出到磁盘上,得到的结果是原来的明文面目全非,如果只分别用一个CipherInputStream和一个CIpherOutputStreamd的话就没有问题。不知道是怎么回事。为了方便我写了以下程序:packagesth;importjava.nio.charset.Charset;importjava.security.*;importjavax.crypto.*;importjava.security.spec.*;importjavax.crypto.spec.*;importjava.io.*;publicclassTest{publicstaticfinalStringKEY_ALG="DES";publicstaticfinalStringALG="DES/CBC/NOPADDING";publicstaticfinalStringENCODING="UTF-8";Keykey;AlgorithmParametersparams;publicTest()throwsException{this.key=KeyGenerator.getInstance(KEY_ALG).generateKey();//产生密钥SecureRandomsr=SecureRandom.getInstance("SHA1PRNG");//获得安全随机数产生器的实例//用DES或者AES加密时,若选择工作模式(CBC,CFB,OFB),要有一个初始向量IV(DES的IV有8个B,AES有16B)byte[]iv=newbyte[8];sr.nextBytes(iv);AlgorithmParameterSpecparamSpec=newIvParameterSpec(iv);this.params=AlgorithmParameters.getInstance(KEY_ALG);params.init(paramSpec);//算法参数用IV初始化完毕}publicbyte[]Encoder(StringplainText,intnum)throwsException{if(num<=0){System.out.println("thenumberofCipherStreammustGT0");returnnull;}System.out.println("Encryptionusing"+ALG);Ciphercf=Cipher.getInstance(ALG);cf.init(Cipher.ENCRYPT_MODE,key,params);//初始化Cipher实例,用于加密;//用ENCODING编码待加密明文放在缓冲区中用于读取ByteArrayInputStreambais=newByteArrayInputStream(plainText.getBytes(ENCODING));CipherInputStreamcis=newCipherInputStream(bais,cf);//包装一个CipherStreamwhile(num-->1){CipherInputStreamtemp=cis;cis=newCipherInputStream(temp,cf);//根据参数或者再包装一个CipherStream}ByteArrayOutputStreambaos=newByteArrayOutputStream();//这里写的不好,当时是认为DES加密时分组是8Bbyte[]b=newbyte[8];inti=cis.read(b);while(i!=-1){baos.write(b,0,i);i=cis.read(b);}baos.flush();byte[]secretData=baos.toByteArray();baos.close();cis.close();bais.close();returnsecretData;}publicStringDecoder(byte[]cipherData,intnum)throwsException{if(num<=0){System.out.println("thenumberofCipherStreammustGT0");returnnull;}System.out.println("Decryptionusing"+ALG);Ciphercf=Cipher.getInstance(ALG);cf.init(Cipher.DECRYPT_MODE,key,params);ByteArrayInputStreambais=newByteArrayInputStream(cipherData);ByteArrayOutputStreambaos=newByteArrayOutputStream();CipherOutputStreamcos=newCipherOutputStream(baos,cf);while(num-->1){CipherOutputStreamtemp=cos;cos=newCipherOutputStream(temp,cf);}byte[]b=newbyte[8];inti=bais.read(b);while(i!=-1){cos.write(b,0,i);i=bais.read(b);}cos.flush();byte[]clearData=baos.toByteArray();cos.close();baos.close();bais.close();//返回明文returnnewString(clearData,Charset.forName(ENCODING));}publicstaticvoidmain(String[]args)throwsException{StringplainText="123abcd一二三!@#¥";System.out.println("plainText:"+plainText);Testtest=newTest();System.out.println("clearText:"+test.Decoder(test.Encoder(plainText,2),2));}}代码应该没有问题,System.out.println("clearText:"+test.Decoder(test.Encoder(plainText,2),2));只需要改变2为1就可以看到如果只包装一个流的话,是可以正常解密的,如果2个或以上,就出现乱码了,我觉得挺奇怪的,理论上是不会的。请大家帮忙!!感谢~!