一个关于CipherInputStream/CipherOutputStream的疑惑

问题描述

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个或以上,就出现乱码了,我觉得挺奇怪的,理论上是不会的。请大家帮忙!!感谢~!

时间: 2024-09-18 02:52:54

一个关于CipherInputStream/CipherOutputStream的疑惑的相关文章

有一个问题我一直很疑惑,一个软件系统是先有文档呢还是先有代码呢,一个UI前台界面是先写js呢还是先写css呢?

问题描述 有一个问题我一直很疑惑,一个软件系统是先有文档呢还是先有代码呢,一个UI前台界面是先写js呢还是先写css呢? 解决方案 一个软件系统是先有文档呢还是先有代码呢?应该是现有文档.这里文档的概念太宽泛,应该说明的是什么文档,细化到什么程度的文档.我们再撸起袖子准备开发一个软件系统的时候,首先得知道的是要开发什么(需求文档),怎么开发(设计文档).注意的是,这里并一定非得把需求文档写的多么细致,考虑每个业务分支逻辑,也不需要将设计文档细化到某个模块的时序图是怎么样的,逻辑判断是怎么样的.因

一个关于 Styled Components 的五分钟介绍

本文讲的是一个关于 Styled Components 的五分钟介绍, CSS 是一个很神奇的语言,你可以在 15 分钟之内就学会一些基础部分,但是如果你要找到一个好的方式来组织你的样式,将会花费数年时间. 这主要是由于语言本身很奇葩.不合常规的是, CSS 是相当有限的,没有变量.循环或者函数.与此同时,它又是相当自由的,你可以随意使用元素.Class.ID 或它们的任意组合. 混乱的样式表 正如你自己所经历过的那样,CSS 通常是很混乱的.虽然有诸如 SASS 和 LESS 这样的预处理器添

《MINECRAFT我的世界 新手完全攻略(第3版)》一2.4 建造一个工作台

2.4 建造一个工作台 大家或许会疑惑,为什么背包已经允许我们合成物品,我们还需要制作一个工作台?很简单,背包里的制作空间只有2×2,只能用来制作一些简单的东西.而工作台提供的空间是3×3,能够满足包括工具制作等各种需求的物品合成.当然你的第一个工作台还是必须在背包中的小格子里合成出来,依照下面的步骤开始合成吧. 1.按下E键,打开背包. 2.还记得我们从树上砍来的木头吗?首先我们要将它们加工成木板.左键在木块堆上点击拾取它们,将其放入合成栏的任意一个格中.搞定,4个单位的一堆木板已经出现在右侧

SEO必然将逐渐趋于正规化

  随着百度搜索引擎算法的不断调整,越来越多的SEOer感觉到无比的压力.因为他们不够自信,他们知道不够相信自身网站的价值所在.由于对SEO知识的缺乏,无法真正完全理解SEO真谛.在实际操作过程中难免会存在诸多问题,一部分是由于自身原因,另一部分是不可控因素.通过百度搜索引擎算法的调整,毫无疑问百度将进一步采取措施,将不正规SEO逐渐摒弃,越来越趋于正规化.作为运用SEO的营销者,必须首先有所觉悟,从用户角度出发,让搜索引擎跟着我们的步伐前进,而不是被动行事,搜索引擎变化什么我们研究什么.因此,

看我如何换链接把新站排名做到百度前三

之前很多SEO这块的朋友都跟我说交换友情链接好难,或者没有平台,及时有了平台,也不知道网站交换链接的时候需要注意哪些问题.或者有的站长说换链接还不容易吗,登录后台,天津爱连接词,添加网址,确定,刷新,然后一个拉手合作的表情发过去,好了,请查看.其实这个问题对于很多的站长或者新站长来说都是一个未知数.这段时间我公司在培养一个新人做SEO,就是从友情链接做起,我觉得这个很能看出一个人,以前从来也没去写交换链接相关的文章,刚好通过这次机会,把最近的培训心得总结了一下,希望在此,通过我这几天的实践对友情

浅谈百度新功能:做好用户体验没有想象中难

对于seo而言,做到最后其实就是为了做好用户体验,因而seoer就不得不重要用户体验.那么,seoer又该如何才能做好用户体验呢?对此笔者以百度最近新添加的功能作为引子,供站长们参考. 首先来看下百度在5月中上线的"添加至百度首页"功能,使用该功能的话就可在百度首页的导航栏里直接访问所添加的网站.这一功能的话,对于SEO是否有影响暂时不得而知.   此功能如同我们常用的收藏夹,不同的是该功能还会智能化的根据用户对网站的访问频率给予自动添加,而用户不需要则可自己删减.而从一功能上,很大的

汇编翻转总结及答复(第7周)

学生 总结内容 回复 1147 div指令,内存寻址,数组用dup设置内存空间重复的值,根据指令,分析操作数的类型和地址   1104 3个关键词:除法,dup操作符,汇编结构体2个收获:1.使用div指令进行除法运算,也分为除数的位数,有一点疑问就是如果我的除数是0,那运行会不会是像C语言那样报错呢,那如果报错,怎样能避免或者检测这个除数的值呢?2.dup可以进行数据的重复,类似于数组的赋值,可以非常简单直白的把值给定,还不需要花费很大空间去声明,那这个dup指令我如果定义50个字节栈段都为0

加盐密码哈希:如何正确使用

如果你是Web开发者你很可能需要开发一个用户账户系统.这个系统最重要的方面就是怎样保护用户的密码.存放帐号的数据库经常成为入侵的目标所以你必须做点什么来保护密码以防网站被攻破时发生危险.最好的办法就是对密码进行加盐哈希这篇文章将介绍它是如何做到这点. 在对密码进行哈希加密的问题上人们有许多争论和误解这大概是由于网络上广泛的误传吧.密码哈希是一件非常简单的事情但是依然有很多人理解错误了.本文阐述的并不是进行密码哈希唯一正确的方法但是会告诉你为什么这样是正确的. 郑重警告如果你在试图编写自己的密码哈

JAVA小题再次登陆

问题描述 [color=#FF0000]编写一个方法求一个DOUBLE值得向右取整,再写一个方法求他的向左取整,数d的向右取整是大于等于d的最小整数,d的向左取整是小于等于d的最大整数,例如5.4向右取整是6,向左取整是5.麻烦大哥解惑[/color] 解决方案 解决方案二:Math类里有,好像一个是ceil.一个是啥,忘了,你查查解决方案三:java类库里提供的有在java.long.Math里一个是ceil一个是floor具体去参考一下API吧解决方案四:引用2楼wodesky1998的回复