精华内容
参与话题
问答
  • 对称加密和非对称加密(一)初步理解

    万次阅读 多人点赞 2018-12-26 23:23:21
    先查大范围 专业术语 再查小范围 便于... 从而出现了:对称加密和非对称加密。 二、对称加密和非对称加密 1. 对称加密 对称加密指的就是加密和解密使用同一个秘钥,所以叫做对称加密对称加密只有一个秘钥,...

    先查大范围  专业术语  再查小范围  便于理解 宏观概念

    然后针对小范围的点,去精准查询  理解细节

     

    一、面临的问题: 密钥分发

    在加密算法之外,面临一个问题,那就是:秘钥的分发。就是说,解密方如何获得加密方的秘钥呢? 从而出现了:对称加密和非对称加密。

    二、对称加密和非对称加密

    1. 对称加密

    对称加密指的就是加密和解密使用同一个秘钥,所以叫做对称加密。对称加密只有一个秘钥,作为私钥。

    常见的对称加密算法:DES,AES,3DES等等。

     

    2. 非对称加密

    非对称加密指的是:加密和解密使用不同的秘钥,一把作为公开的公钥,另一把作为私钥。公钥加密的信息,只有私钥才能解密。私钥加密的信息,只有公钥才能解密。

    常见的非对称加密算法:RSA,ECC

     

    3. 区别

    对称加密算法相比非对称加密算法来说,加解密的效率要高得多。但是缺陷在于对于秘钥的管理上,以及在非安全信道中通讯时,密钥交换的安全性不能保障。所以在实际的网络环境中,会将两者混合使用.

     

    例如针对C/S模型,

    1. 服务端计算出一对秘钥pub/pri。将私钥保密,将公钥公开。

    2. 客户端请求服务端时,拿到服务端的公钥pub。

    3. 客户端通过AES计算出一个对称加密的秘钥X。 然后使用pub将X进行加密。

    4. 客户端将加密后的密文发送给服务端。服务端通过pri解密获得X。

    5. 然后两边的通讯内容就通过对称密钥X以对称加密算法来加解密。

    对称加密和非对称加密的区别

    1对称加密:加密解密用同一个密钥,被黑客拦截不安全

     

    2非对称加密:公钥加密,私钥解密;公钥可以公开给别人进行加密,私钥永远在自己手里,非常安全,黑客拦截也没用,因为私钥未公开。著名的RSA加密算法用的就是非对称加密。

     

     

     

    第一步:ipB先给A发送B公钥,ipA用B公钥加密A公钥发送给ipB,ipB拿到后,用B私钥去取里面内容,ipB拿到A公钥。

    第二步:双方通信用对方公钥直接加密后发送。接收方用自己的私钥去解密。

     

     

     

    举例子理解:

    最简单易懂的非对称加密

    北京的张三发了一个快递到广州的李四,途中经过了上海,上海快递中心出现了一个黑客老王,他偷偷打开了张三给李四的快递,然后偷偷把里边的衣服剪烂,再按照原样包装好发往广州,可以看到对于这样简单包装的传输在中途是可以偷偷修改里边的东西。

            HTTP的数据包是明文传输,也即是如果中途某个黑客嗅探到这个HTTP包,他可以偷偷修改里边包的内容,至于张三跟李四是互相不知道这个动作的,因此我们必须要有一个方案来防止这种不安全的篡改行为,有个方法就是加密!

    非对称加密

     

            张三将衣服放到一个保险箱里边锁起来,他打了个电话告诉李四保险箱开柜密码是1234,而黑客老王不知道密码,所以他看不到保险箱里边的东西,李四收到快递后用预先沟通好的密码就可以打开保险箱了。

            这里保护的手段就是张三对物品进行加密,同时给了告诉李四解密的方法!

            那如果现在要求张三的密码只能通过快递传给李四呢?如果张三直接传密码给李四,老王如果嗅探到这个快递,那老王也知道密码了,这就无法保护快递的安全性了。因此还需要有个方案,让张三能够告诉李四密码的同时,老王又无法查看到张三跟李四通信的数据。

     

    非对称加密在这个时候就发挥作用了,来看看怎么回事:

    张三拥有两把钥匙,一把叫做公钥,一把叫做私钥。公钥是公开让全社会都知道,没关系,张三告诉所有人,你们要传递数据给我的时候请先用这个密钥(公钥)去加密一下你们的数据,加密后的数据只能通过张三私自藏着的私钥才能解密。

     

    回到刚刚例子,

    张三先发给保险柜(张三公钥)给李四,

    接着李四把自己的保险柜(李四公钥)放到张三的保险柜(即使用张三的公钥加密李四的公钥)里边发还给张三,

    接着张三拿到李四的数据包后,用自己的私钥解开了外层保险柜(张三的公钥),拿到了里边李四保险柜(李四的公钥)。

    此时李四跟张三都有了各自的公钥(并且都有他们自己的私钥),接着只要保证每次互相传递数据的时候,把数据放在对方的保险柜里边即可(即每次都用对方的公钥加密数据),这样无论如何,老王都无法解开保险柜(因为只有各自的私钥才能解开各自的保险柜)。

     

     

     

    展开全文
  • 对称加密

    2019-11-07 14:20:36
    对称加密1.编码2.DES2.1 什么是DES2.2 加密和解密3. AES4. 对称加密方式的选择 “对称加密: 也称为对称密码, 是1 指在加密和解码时使用同一秘钥的加密方式” 1.编码 现代的密码都是建立在计算机的基础之上的,...

    “对称加密: 也称为对称密码, 是指在加密和解码时使用同一秘钥的加密方式”

    在这里插入图片描述

    1.编码

        现代的密码都是建立在计算机的基础之上的,这是因为现代的密码所处理的数据量非常大,而且密码算法也非常复杂,不借助计算机的力量就无法完成加密和解密的操作。
        计算机的操作对象并不是文字,而是由0和1排列而成的比特序列。无论是文字、图像、声音、视频还是程序,在计算机中都是用比特序列来表示的。执行加密操作的程序,就是将表示明文的比特序列转换为表示密
    文的比特序列。
        将现实世界中的东西映射为比特序列的操作称为编码(encoding)。例如midnight(深夜)这个词,我们可以对其中的每个字母逐一进行编码,这种编码规则叫作ASCII。
    在这里插入图片描述
        注意这里的m --> 01101101这一转换并不是加密而是编码。尽管在人类看来0和1的序列跟密码没什么两样,但计算机却可以“看懂"这些比特序列,并很快地反应出其所对应的字符 midnight
    在这里插入图片描述

    2.DES

    2.1 什么是DES

        DES(DataEncryptionStandard)是1977年美国联邦信息处理标准(FIPS)中所采用的一种对称密码(FIPS46.3)。DES一直以来被美国以及其他国家的政府和银行等广泛使用。然而,随着计算机的进步,现在DES已经能够被暴力破解,强度大不如前了。
    RSA公司举办过破泽DES密钥的比赛(DESChallenge),我们可以看一看RSA公司官方公布的比赛结果:

    • 1997年的DES Challenge1中用了96天破译密钥
    • 1998年的DES ChallengeIl-I中用了41天破译密钥
    • 1998年的DES ChallengeII-2中用了56小时破译密钥
    • 1999年的DES ChallengeIll中只用了22小时15分钟破译密钥

        由于DES的密文可以在短时间内被破译,因此除了用它来解密以前的密文以外,现在我们不应该再使用DES了。

    2.2 加密和解密

        DES是一种将64比特的明文加密成64比特的密文的对称密码算法,它的密钥长度是56比特。尽管从规格上来说,DES的密钥长度是64比特,但由于每隔7比特会设置一个用于错误检查的比特,因此实质上其密钥长度是56比特。

        DES是以64比特的明文(比特序列)为一个单位来进行加密的,这个64比特的单位称为分组。一般来说,以分组为单位进行处理的密码算法称为分组密码(blockcipher),DES就是分组密码的一种。

        DES每次只能加密64比特的数据,如果要加密的明文比较长,就需要对DES加密进行迭代(反复),而迭代的具体方式就称为模式(mode)。

    • DES的加密与解密 - 图例
      在这里插入图片描述## 2.3 三重DES

        现在DES已经可以在现实的时间内被暴力破解,因此我们需要一种用来替代DES的分组密码,三重DES就是出于这个目的被开发出来的。

        三重DES(triple-DES)是为了增加DES的强度,将DES重复3次所得到的一种密码算法,通常缩写为3DES。

    • 三重DES的加密
      在这里插入图片描述

        明文经过三次DES处理才能变成最后的密文,由于DES密钥的长度实质上是56比特,因此三重DES的密钥长度就是56×3=168比特。

        从上图我们可以发现,三重DES并不是进行三次DES加密(加密–>加密–>加密),而是加密–>解密–>加密的过程。在加密算法中加人解密操作让人感觉很不可思议,实际上这个方法是IBM公司设计出来的,目的是为了让三重DES能够兼容普通的DES。

        当三重DES中所有的密钥都相同时,三重DES也就等同于普通的DES了。这是因为在前两步加密–>解密之后,得到的就是最初的明文。因此,以前用DES加密的密文,就可以通过这种方式用三重DES来进行解密。也就是说,三重DES对DES具备向下兼容性。
        如果密钥1和密钥3使用相同的密钥,而密钥2使用不同的密钥(也就是只使用两个DES密钥),这种三重DES就称为DES-EDE2(下图)。EDE表示的是加密(Encryption) -->解密(Decryption)–>加密(Encryption)这个流程。

        密钥1、密钥2、密钥3全部使用不同的比特序列的三重DES称为DES-EDE3。

    在这里插入图片描述尽管三重DES目前还被银行等机构使用,但其处理速度不高,而且在安全性方面也逐渐显现出了一些问题。 (新的项目不要最好再使用这种方式了)

    3. AES

        AES(Advanced Encryption Standard)是取代其前任标准(DES)而成为新标准的一种对称密码算法。全世界的企业和密码学家提交了多个对称密码算法作为AES的候选,最终在2000年从这些候选算法中选出了一种名为Rijndael的对称密码算法,并将其确定为了AES。

        Rijndael是由比利时密码学家Joan Daemen和Vincent Rijmen设汁的分组密码算法,今后会有越来越多的密码软件支持这种算法。

    Rijndael的分组长度为128比特,密钥长度可以以32比特为单位在128比特到256比特的范围内进行选择(不过在AES的规格中,密钥长度只有128、192和256比特三种)。

    4. 对称加密方式的选择

    DES、三重DES和AES等对称密码,那么到底应该使用哪一种对称密码算法呢?

    1. 今后最好不要将DES用于新的用途,因为随着计算机技术的进步,现在用暴力破解法已经能够在现实的时间内完成对DES的破译。但是,在某些情况下也需要保持与旧版本软件的兼容性。
    2. 出于兼容性的因素三重DES在今后还会使用一段时间,但会逐渐被AES所取代。
    3. 应该使用的算法是AES(Rijndael),因为它安全、快速,而且能够在各种平台上工作。此外,由于全世界的密码学家都在对AES进行不断的验证,因此即便万一发现它有什么缺陷,也会立刻告知全世界并修复这些缺陷。

    一般来说,我们不应该使用任何自制的密码算法,而是应该使用AES。因为AES在其选定过程中,经过了全世界密码学家所进行的高品质的验证工作,而对于自制的密码算法则很难进行这样的验证。

    展开全文
  • 最全加密算法之对称加密和非对称加密

    万次阅读 多人点赞 2016-08-27 10:27:30
    常见加密算法 : DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合;  3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高; RC2和 RC4:用变...



    常见加密算法 :

    DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合; 

    3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高;

    RC2和 RC4:用变长密钥对大量数据进行加密,比 DES 快;

    IDEA(International Data Encryption Algorithm)国际数据加密算法:使用 128 位密钥提供非常强的安全性;

    RSA:由 RSA 公司发明,是一个支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的;

    DSA(Digital Signature Algorithm):数字签名算法,是一种标准的 DSS(数字签名标准);

    AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高,目前 AES 标准的一个实现是 Rijndael 算法;

    BLOWFISH,它使用变长的密钥,长度可达448位,运行速度很快; 

    其它算法,如ElGamal、Deffie-Hellman、新型椭圆曲线算法ECC等。 比如说,MD5,你在一些比较正式而严格的网站下的东西一般都会有MD5值给出,如安全焦点的软件工具,每个都有MD5。严格来说MD5并不能算是一种加密算法,只能说是一种摘要算法(数据摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名、数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密。数据摘要算法也被称为哈希(Hash)算法、散列算法。

    MD5分类:

    1、CRC8、CRC16、CRC32

    CRC(Cyclic Redundancy Check,循环冗余校验)算法出现时间较长,应用也十分广泛,尤其是通讯领域,现在应用最多的就是 CRC32 算法,它产生一个4字节(32位)的校验值,一般是以8位十六进制数,如FA 12 CD 45等。CRC算法的优点在于简便、速度快,严格的来说,CRC更应该被称为数据校验算法,但其功能与数据摘要算法类似,因此也作为测试的可选算法。

    在 WinRAR、WinZIP 等软件中,也是以 CRC32 作为文件校验算法的。一般常见的简单文件校验(Simple File Verify – SFV)也是以 CRC32算法为基础,它通过生成一个后缀名为 .SFV 的文本文件,这样可以任何时候可以将文件内容 CRC32运算的结果与 .SFV 文件中的值对比来确定此文件的完整性。

    与 SFV 相关工具软件有很多,如MagicSFV、MooSFV等。

    2、MD2 、MD4、MD5

    这是应用非常广泛的一个算法家族,尤其是 MD5(Message-Digest Algorithm 5,消息摘要算法版本5),它由MD2、MD3、MD4发展而来,由Ron Rivest(RSA公司)在1992年提出,被广泛应用于数据完整性校验、数据(消息)摘要、数据加密等。MD2、MD4、MD5 都产生16字节(128位)的校验值,一般用32位十六进制数表示。MD2的算法较慢但相对安全,MD4速度很快,但安全性下降,MD5比MD4更安全、速度更快。

    在互联网上进行大文件传输时,都要得用MD5算法产生一个与文件匹配的、存储MD5值的文本文件(后缀名为 .md5或.md5sum),这样接收者在接收到文件后,就可以利用与 SFV 类似的方法来检查文件完整性,绝大多数大型软件公司或开源组织都是以这种方式来校验数据完整性,而且部分操作系统也使用此算法来对用户密码进行加密,另外,它也是目前计算机犯罪中数据取证的最常用算法。

    与MD5 相关的工具有很多,如 WinMD5等。

    3、SHA1、SHA256、SHA384、SHA512

    SHA(Secure Hash Algorithm)是由美国专门制定密码算法的标准机构-- 美国国家标准技术研究院(NIST)制定的,SHA系列算法的摘要长度分别为:SHA为20字节(160位)、SHA256为32字节(256位)、 SHA384为48字节(384位)、SHA512为64字节(512位),由于它产生的数据摘要的长度更长,因此更难以发生碰撞,因此也更为安全,它是未来数据摘要算法的发展方向。由于SHA系列算法的数据摘要长度较长,因此其运算速度与MD5相比,也相对较慢。

    SHA1的应用较为广泛,主要应用于CA和数字证书中,另外在互联网中流行的BT软件中,也是使用SHA1来进行文件校验的。

    4、RIPEMD、PANAMA、TIGER、ADLER32 等

    RIPEMD是Hans Dobbertin等3人在对MD4,MD5缺陷分析基础上,于1996年提出来的,有4个标准128、160、256和320,其对应输出长度分别为16字节、20字节、32字节和40字节。

    TIGER由Ross在1995年提出。Tiger号称是最快的Hash算法,专门为64位机器做了优化。


    常用的加密算法有对称加密和非对称加密两大类型:


    对称加密

    简介:

    对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算法,就是加密密钥能够从解密密钥中推算出来,同时解密密钥也可以从加密密钥中推算出来。而在大多数的对称算法中,加密密钥和解密密钥是相同的,所以也称这种加密算法为秘密密钥算法或单密钥算法。它要求发送方和接收方在安全通信之前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信性至关重要。


    特点:

    对称加密算法的特点是算法公开、计算量小、加密速度快、加密效率高。

    不足之处是,交易双方都使用同样钥匙,安全性得不到保证。此外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的惟一钥匙,这会使得发收信双方所拥有的钥匙数量呈几何级数增长,密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。而与公开密钥加密算法比起来,对称加密算法能够提供加密和认证却缺乏了签名功能,使得使用范围有所缩小。在计算机专网系统中广泛使用的对称加密算法有DES和IDEA等。美国国家标准局倡导的AES即将作为新标准取代DES。


    具体算法:DES算法3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法。

    原理应用:对称加密算法的优点在于加解密的高速度和使用长密钥时的难破解性。假设两个用户需要使用对称加密方法加密然后交换数据,则用户最少需要2个密钥并交换使用,如果企业内用户有n个,则整个企业共需要n×(n-1) 个密钥,密钥的生成和分发将成为企业信息部门的恶梦。对称加密算法的安全性取决于加密密钥的保存情况,但要求企业中每一个持有密钥的人都保守秘密是不可能的,他们通常会有意无意的把密钥泄漏出去--如果一个用户使用的密钥被入侵者所获得,入侵者便可以读取该用户密钥加密的所有文档,如果整个企业共用一个加密密钥,那整个企业文档的保密性便无从谈起。

    对称加密算法中最经典的算法莫过于DES加密算法。DES加密采用的是分组加密的方法,使用56位密钥加密64位明文,最后产生64位密文。DES算法的基本流程如图6-2所示。

     

     

     

    图6-2  DES加密算法基本流程

    现在对图6-2的整个流程做简要的分析。DES对64位的明文分组M进行操作,M经过一个初始置换IP置换成m0,将m0明文分成左半部分和右半部分m0=(L0,R0),各32位长。然后进行16轮完全相同的运算,这些运算称为函数f,在运算过程中,数据与密匙结合。经过16轮运算之后,可以看到第16轮运算,将右侧第15轮运算的结果(R15)作为左侧运算的最终结果(L16),而右侧最后的结果(R16)为左侧第15轮运算结果(L15)和函数f运算结果的异或运算所得。此后,再将左、右部分合在一起经过一个逆置换,输出密文。

    实际加密过程要分成两个同时进行的过程,即加密过程和密钥生成过程,如图6-3所示。结合图6-2和图6-3简单讲解密钥生成过程。

     

    图6-3  加密与密钥生成

    如图6-3所示,在16轮循环的每一轮中,密匙位移位,然后再从密匙的64位中选出48位。通过一个扩展置换将数据的右半部分扩展成48位,并通过一个异或操作替代成新的32位数据,在将其置换一次。这四步运算构成了图6-2中的函数f。然后,通过另一个异或运算,函数f的输出与左半部分结合,其结果成为新的右半部分,原来的右半部分成为新的左半部分。该操作重复16次。

    DES算法的解密过程和加密过程几乎完全相同,只是使用密钥的顺序相反。

    关于DES算法的更加详细的细节不在本书的讲解范围之内,请读者参考相关资料。

    NIST(National Institute of Standards and Technology,美国国家标准技术研究院)在1999年发布了新的DES加密标准,3DES取代DES成为新的加密标准。3DES采用168位的密钥,三重加密,但速度较慢。之后,又出现了AES(Advanced Encryption Standard,先进加密标准)等高级对称机密算法。

    TripleDES加密算法

    由于DES算法安全性方面的原因,为了提高DES算法的抗攻击性,因此提出了Triple-DES算法。

    Triple-DES算法的基本原理是:用两个密钥对数据进行3次加密/解密运算。即首先使用第一个密钥对数据进行加密,然后用第二个密钥对其进行解密,最后用第一个密钥再加密。这两个密钥可以是同一个,也可以不同,它们也可以来源于一个128位密钥,只是在加密/解密时将其分割成两个64位的密钥,分别轮换使用这两个64位密钥去完成加密/解密运算。Triple-DES算法保留了DES算法运算速度快的特点,通过增加运算次数和密钥长度(两个64位密钥相当于128位密钥)来增加破解者的破解时间,但是从密码学本身来说,其安全强度并没有增加。

    RC系列算法

    现在我们用到的RC系列算法包括RC2、RC4、RC5、RC6算法,其中RC4是序列密码算法,其他三种是分组密码算法。

    (1)  RC2算法

    该算法设计的目的是用来取代DES算法,它采用密钥长度可变的对明文采取64位分组的分组加密算法,属于Festel网络结构。

    (2)  RC4算法

    该算法是一个密钥长度可变的面向字节流的加密算法,以随机置换为基础。该算法执行速度快,每输出1字节的结果仅需要8~16字节的机器指令。RC4算法比较容易描述,它首先用8~2048位可变长度的密钥初始化一个256字节的状态矢量S。S的成员标记为S[0],S[1],…,S[255],整个置换过程都包含0~255的8比特数。对于加密和解密,设字节数据为K,由S中256个元素按一定方式选出一个元素生成,每生成一个K值,元素中的数据就要被重新置换一次。RC4初始化的伪代码如代码清单6-1所示。

    代码清单6-1  RC4初始化的伪代码

    for i=0 to 255

    {

      S[i]=i;

      T[i]=K[i mod KeyLen ];

    }

    j=0;

    for i=0 to 255

    {

      j=(j+T[i]+S[i]) mod 256;

    swap(S[i],S[j];

    }

    如代码清单6-1所示,初始化开始时,S的元素按从0到255依次赋值,同时建立一个临时矢量T。如果密钥K的长度为256字节,则将K赋值给T。否则,若密钥长度为KeyLen字节,则将K的值赋给T的前KeyLen个元素,并循环重复用K余下的元素赋给T剩下的元素。从“j=0”开始,用T产生S的初始置换。从S[0]~S[255],对每个S[i]根据T[i]确定的方案,将S[i]置换成S中的另一字节。

    在完成S的初始化之后,输入密钥将被抛弃,接下来将使用密钥流,生成密钥流的伪代码如代码清单6-2所示。

    代码清单6-2  生成密钥流

    i=0;

    j=0;

    while(true)

    {

       i=(i+1) mod 256;

       j=(j+S[i]) mod 256;

       swap(S[i],j[i];

       T=(S[i]+S[j]) mod 256;

       K=S[T];

    }

    如代码清单6-2所示,密钥流的生成是从S[0]到S[255],对每个S[i]根据当前S的值将S[i]与S中的另一字节替换,当S[255]完成置换后操作继续重复。在加密过程中将K的值与下一明文字节异或,解密过程中将K的值与下一密文字节异或即可。

    (3)  RC5算法

    该算法是一种分组长度、密钥长度、加密迭代轮数都可变的分组加密算法。该算法主要包含三部分内容:密钥扩展、加密算法和解密算法。该算法包含三个参数:w(字的长度,单位:位)、r(迭代次数)、b(密钥长度,单位:字节)。由于RC5算法需要(2r+2)个w位密钥,所以需要密钥扩展。

    通过密钥扩展,把密钥K扩展成密钥阵S,它由K所决定的t=2(r+1)个随机二进制字构成。密钥扩展算法利用了两个幻常数:

    Pw=Odd((e-2)2w[1]

    Qw=Odd((Φ-1)2w[2]

    函数Odd(x)的结果为与x最近的奇整数。密钥扩展的第一步是将密钥K转换成字格式,利用K的各字节构造字阵L。密钥扩展的第二步是利用模232线性同余算法初始化S阵。密钥扩展的第三步是L阵和S阵混合。

    加密过程也很简单。假设选用的数据分组长度为2w位(w允许的值有16、32和64),迭代次数为r轮(r为0~255)。首先将明文划分成两个w位的字A和B,运算过程如代码清单6-3所示。

    代码清单6-3  RC5算法加密过程

    A=A+S0;

    B=B+S1;

    for i=1 to r

    {

      A=((A+B)<<<B))+S2i;

      B= ((B+A) <<<A)) +S2i+1;

    }

    代码清单6-3的结果输出到寄存器A和B中。

    解密过程是加密过程的逆运算,基本过程如代码清单6-4所示。

    代码清单6-4  RC5算法解密过程

    for i=r down to 1

    {

      B=((B- S2i+1)>>>A)+A;

      A=((A- S2i)>>>B)+B;

    }

    B=B-S1;

    A=A-S0;

    说明 加密和解密过程中的加减都是模2w的,表示逐位异或。<<<表示循环左移,>>>表示循环右移。

    (4)  RC6算法

    RC6秉承了RC5设计简单、广泛使用数据相关的循环移位思想,同时增强了抵抗攻击的能力,改进了RC5中循环移位的位数依赖于寄存器中所有位的不足。

    RC6的特点是输入的明文由原先2个区块扩展为4个区块,另外,在运算方面则是使用了整数乘法,而整数乘法的使用则在每一个运算回合中增加了扩散(diffusion)的行为,并且使得即使很少的回合数也有很高的安全性。同时,RC6中所用的操作可以在大部分处理器上高效率地实现,提高了加密速度。RC6是一种安全、架构完整而且简单的区块加密法。它提供了较好的测试结果和参数方面相当大的弹性。RC6可以抵抗所有已知的攻击,能够提供AES所要求的安全性,可以说是近几年来相当优秀的一种加密法。

    Rijndael算法

    Rijndael是一个反复运算的加密算法,它允许可变动的数据区块及密钥的长度。数据区块与密钥长度的变动是各自独立的。

    在Rijndael算法中定义了两个名词:

    1)        State:在运算过程中所产生的中间值,是一个4×Nb的矩阵,Nb可由数据长度除以32位求得,也就是把数据分割成Nb个区块。

    2)        Cipher Key:用来做加密运算的密钥,形式是一个4×Nk的矩阵,Nk可由金钥长度除以32位求得,也就是把密钥分割成Nk个32位的子密钥。

    在Rijndael算法中,运算的回合数(Nr)是由Nb及Nk决定的,回合数的变动定义如表6-1所示。

                    表6-1  Rijndael算法回合变动定义

    Nr

    Nb=4

    Nb=6

    Nb=8

    Nk=4

    10

    12

    14

    Nk=6

    12

    12

    14

    Nk=8

    14

    14

    14

    在Rijndael中使用了许多字节层级的运算,而这些运算是以GF(28)为基础架构。也有一些采用了4-byte的字组运算。各种运算的定义如下:

    (1) GF(28)的定义

    假设一个字节b由b7b6b5b4b3b2b1b0组成,可以把这些bi想象成一个7次多项式的系数,而这些系数不是0就是1:

    b7 x7+ b6 x6+ b5 x5+ b4 x4+ b3 x3+ b2 x2+ b1 x + b0

    例如,(57)16的二进制表示法为(0101,0111)2表示成多项式,则为:

    x6+ x4+ x2+ x + 1

    (2)加法

    两个多项式的加法,则是定义为相同指数项的系数和再模2,简单地说,就是作EXOR运算(1+1=0)。例如:

    (57)16+(83)16=(01010111)2+(10000011)= (11010100)= (D416

    或是

    (x6+x4+x2+x+1)+(x7+x+1)=x7+x6+x4+x2

    (3)乘法

    在乘法运算中,多项式相乘之后的结果很容易造成溢位的问题,解决溢位的方式是把相乘的结果,再模余一个不可分解的多项式m(x)。在Rijndael中,定义一个这样的多项式为m(x)=x8+x4+x3+x+1或是(11B)16例如:

    (57)16‧(83)16

     =(x6+ x4+ x2+ x + 1)‧(x7+ x + 1)

     =x13+ x11+ x9+ x8+ x7+x7+ x5+ x3+ x2+x+x6+ x4+ x2+ x + 1

    =(x13+x11+x9+x8+x6+x5+x4+x3+1+x13+x11+x9+x8+x6+x5+x4+x3+1)mod(x8+x4+x3+x+1)

    = x7+ x6+ 1

    =(C116

    (4)乘以X

    若把b(x)乘以x,得到

    b7 x8+ b6 x7+ b5 x6+ b4 x5+ b3 x4+ b2 x3+ b1 x2 + b0x

    若b7=0,不会发生溢位问题,答案即是正确的;若b7=1,发生溢位问题,必须减去m(x)。可以把这种运算表示为xtime(x),其运算方式为left shift(若溢位则和(1B)16做EXOR运算),例如:

     ‘57’· ‘13’ = ‘FE’

    ‘57’ · ‘02’ = xtime(57) = ‘AE’

    ‘57’ · ‘04’ = xtime(AE) = ‘47’

    ‘57’ · ‘08’ = xtime(47) = ‘8E’

    ‘57’ · ‘10’ = xtime(8E) = ‘07’

    ‘57’ · ‘13’ = ‘57’ · (‘01’⊕‘02’⊕‘10’) = ‘57’⊕‘AE’⊕‘07’ = ‘FE’

    Rijndael算法分为四个步骤:

    步骤 1  字节转换。

    字节转换是一个以字节为单位的非线性取代运算,取代表(S-box)是经过2个运算过程而建立,并且是可逆的。首先找出每个字节在GF(28)中的乘法反元素;接着经过1个仿射(Affine)转换运算,转换运算的定义如图6-4所示。

     

     

     

    图6-4  转换运算定义

    取代表生成之后就可以进行字节取代运算。取代运算的示意图如图6-5所示。

    图6-5  取代运算示意图

    进行如图6-5的取代运算之后,结果如图6-6所示。

    图6-6 取代运算后的S-Box

    说明 字节取代转换的反运算:计算仿射对应之后的相反运算可得到S-1-box,以此S-1-box做字节取代(Subbytes)即可。

    步骤 2  移行转换。

    在这个转换中,State的每一行以不同的偏移量做环状位移:第0 行不动,第1 行位移1 C个字节,第2 行位移2 C个字节,第3 行位移3 C个字节。位移的偏移量C1C2C3跟区块的数目(Nb)有关,关系见图6-7。

     

    图6-7  C1 C2 C3与区块数目(Nb)的关系

    移行转换(Shift rows)运算对于State 的影响如图6-8所示。

    图6-8  移行转换对State的影响

    说明 移行转换的反运算:对第2、第3 及第4 行做Nb-C1Nb-C2Nb-C3个字节的环状位移即可。

    步骤 3  混列转换。

    在这个转换中,把State当做一个GF(28)中的多项式。并且对一个固定的多项式CX)作乘法,如果发生溢位,则再模X4 +1. 表示如下:

    CX) ='03' X3 +'01' X2 +'01' X +'02'

    CX)与X4 +1互质,令

    BX) = CX)⊕ AX

    以矩阵乘法表示如图6-9所示。

    图6-9  混列转换的矩阵乘法表示

    State经过混列(Mix columns)运算之后的变化如图6-9所示。

     

     

     

    图6-9  混列运算对State的影响

    说明 混列转换的反运算是乘以一个特殊的多项式DX):

    '03' X3 +'01' X2 +'01' X +'02)⊕ DX

    ='01' DX

    ='0B' X3 +'0D' X2 +'09' X +'0E'

    步骤 4  轮密钥加。

    这个运算主要是把每一个回合密钥(Roundkey)透过简单的Bitwise exor加入到每一个State中,如图6-10所示。

    图6-10  Bitwise exor加入后的State

    说明 此时Add round key的逆是它自身。

     


    ------------------注:本文部分内容改变自《.NET 安全揭秘》

    [1]其中,e为自然对数底,e= 2.718281828459……

    [2]其中,Φ为黄金分割率。


                                                        非对称加密


    对称加密算法是一种密钥的保密方法。

    非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。

    另一方面,甲方可以使用乙方的公钥对机密信息进行签名后再发送给乙方;乙方再用自己的私匙对数据进行验签。

    甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。 非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要。

    非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。


    起源:W.Diffie和M.Hellman 1976年在IEEE Trans.on Information刊物上发表了“ New Direction in Cryptography”文章,提出了“非对称密码体制即公开密钥密码体制”的概念,开创了密码学研究的新方向。

    工作原理:

    公钥和私钥的产生

    假设Alice想要通过一个不可靠的媒体接收Bob的一条私人讯息。她可以用以下的方式来产生一个公钥和一个私钥:

    随意选择两个大的质数p和q,p不等于q,计算N=pq。

    根据欧拉函数,不大于N且与N互质的整数个数为(p-1)(q-1)

    选择一个整数e与(p-1)(q-1)互质,并且e小于(p-1)(q-1)

    用以下这个公式计算d:d×e≡1(mod(p-1)(q-1))

    将p和q的记录销毁。

    (N,e)是公钥,(N,d)是私钥。(N,d)是秘密的。Alice将她的公钥(N,e)传给Bob,而将她的私钥(N,d)藏起来。

    加密消息

    假设Bob想给Alice送一个消息m,他知道Alice产生的N和e。他使用起先与Alice约好的格式将m转换为一个小于N的整数n,比如他可以将每一个字转换为这个字的Unicode码,然后将这些数字连在一起组成一个数字。假如他的信息非常长的话,他可以将这个信息分为几段,然后将每一段转换为n。用下面这个公式他可以将n加密为c:

    加密公式加密公式

    计算c并不复杂。Bob算出c后就可以将它传递给Alice。

    解密消息

    Alice得到Bob的消息c后就可以利用她的密钥d来解码。她可以用以下这个公式来将c转换为n:

    解密公式解密公式

    得到n后,她可以将原来的信息m重新复原。

    解码的原理是

    解码原理1解码原理1

    以及ed≡1(modp-1)和ed≡1(modq-1)。由费马小定理可证明(因为p和q是质数)

    解码原理3解码原理3

    解码原理2解码原理2

    这说明(因为p和q是不同的质数,所以p和q互质)

    解码原理5解码原理5





    主要应用:

    非对称加密(公钥加密):指加密和解密使用不同密钥的加密算法,也称为公私钥加密。假设两个用户要加密交换数据,双方交换公钥,使用时一方用对方的公钥加密,另一方即可用自己的私钥解密。如果企业中有n个用户,企业需要生成n对密钥,并分发n个公钥。由于公钥是可以公开的,用户只要保管好自己的私钥即可,因此加密密钥的分发将变得 十分简单。同时,由于每个用户的私钥是唯一的,其他用户除了可以可以通过信息发送者的公钥来验证信息的来源是否真实,还可以确保发送者无法否认曾发送过该信息。非对称加密的缺点是加解密速度要远远慢于对称加密,在某些极端情况下,甚至能比非对称加密慢上1000倍。

    DSACryptoServiceProvider

    RSACryptoServiceProvider

    //加密

    UnicodeEncoding encoding = new UnicodeEncoding();

    byte[] PasswordBytes = encoding.GetBytes(password);//将密码转换为字节数组RSACryptoServiceProvider crypt=new RSACryptoServiceProvider();//RSA加密算法,非对称PasswordBytes=crypt.Encrypt(password ,false);//加密字节数组,这是加密后的密码值,放入数据库中的表字段中。

    string key=crypt.ToXmlString(true);//输出密钥为XML格式的字符串,且包含私钥,这个字符串要作为数据库表中的一个字段同用户的密码放在一起。

    //解密

    RSACryptoServiceProvider crypt=new RSACryptoServiceProvider();//已随机生成了一个密钥对

    crypt.Clear();//毁掉当前密钥对

    crypt.FromXmlString(key)//输入密钥对,key是从数据库表字段中读取的那个XML格式的字符串,即密钥字段PasswordBytes=crypt.Decrypt(password ,false);//解密字节数组,返回原始密码给用户

    上面方法的一个特点是每个用户对应一个密钥(包含公钥和私钥),它们都是随机生成的,所以各不相同。不过缺点也是很明显的,就是密钥存储在数据库中,如果数据库被攻破密钥就泄漏了。

    还有另外一个方法就是依照上面方法随机生成一个密钥对(包含公钥和私钥),通过ToXmlString(true)方法导出,然后把这个XML字符串格式的密钥放到你的Web程序的Web.config文件的AppSetting节点里面,然后通过FromXmlString(key)方法读入密钥,这样就意味着所有的用户密码都用同一个密钥对加密和解密。


    主要功能:

    非对称加密体系不要求通信双方事先传递密钥或有任何约定就能完成保密通信,并且密钥管理方便,可实现防止假冒和抵赖,因此,更适合网络通信中的保密通信要求。

    主要算法:

    RSA、Elgamal、背包算法、Rabin、HD,ECC(椭圆曲线加密算法)。

    使用最广泛的是RSA算法,Elgamal是另一种常用的非对称加密算法。

    Elgamal由Taher Elgamal于1985年发明,其基础是DiffieˉHellman密钥交换算法,后者使通信双方能通过公开通信来推导出只有他们知道的秘密密钥值[DiffieˉHellman]。DiffieˉHellman是Whitfield Diffie和Martin Hellman于1976年发明的,被视为第一种 非对称加密算法,DiffieˉHellman 与RSA的不同之处在于,DiffieˉHellman不是加密算法,它只是生成可用作对称密钥的秘密数值。在DiffieˉHellman密钥交换过程中,发送方和接收方分别生成一个秘密的随机数,并根据随机数推导出公开值,然后,双方再交换公开值。DiffieˉHellman算法的基础是具备生成共享密钥的能力。只要交换了公开值,双方就能使用自己的私有数和对方的公开值来生成对称密钥,称为共享密钥,对双方来说,该对称密钥是相同的,可以用于使用对称加密算法加密数据。

    与RSA相比,DiffieˉHellman的优势之一是每次交换密钥时都使用一组新值,而使用RSA算法时,如果攻击者获得了私钥,那么他不仅能解密之前截获的消息,还能解密之后的所有消息。然而,RSA可以通过认证(如使用X.509数字证书)来防止中间人攻击,但Diff ieˉHellman在应对中间人攻击时非常脆弱。

    与对称加密算法的区别

    首先,用于消息解密的密钥值与用于消息加密的密钥值不同;

    其次,非对称加密算法比对称加密算法慢数千倍,但在保护通信安全方面,非对称加密算法却具有对称密码难以企及的优势。

    为说明这种优势,使用对称加密算法的例子来强调:

    (图)非对称加密算法(图)非对称加密算法

    Alice使用密钥K加密消息并将其发送给Bob,Bob收到加密的消息后,使用密钥K对其解密以恢复原始消息。这里存在一个问题,即Alice如何将用于加密消息的密钥值发送给 Bob?答案是,Alice发送密钥值给Bob时必须通过独立的安全通信信道(即没人能监听到该信道中的通信)。

    这种使用独立安全信道来交换对称加密算法密钥的需求会带来更多问题:

    首先,有独立的安全信道,但是安全信道的带宽有限,不能直接用它发送原始消息。

    其次,Alice和Bob不能确定他们的密钥值可以保持多久而不泄露(即不被其他人知道)以及何时交换新的密钥值

    当然,这些问题不只Alice会遇到,Bob和其他每个人都会遇到,他们都需要交换密钥并处理这些密钥管理问题(事实上,X9.17是一项DES密钥管理ANSI标准[ANSIX9.17])。如果Alice要给数百人发送消息,那么事情将更麻烦,她必须使用不同的密钥值来加密每条消息。例如,要给200个人发送通知,Alice需要加密消息200次,对每个接收方加密一次消息。显然,在这种情况下,使用对称加密算法来进行安全通信的开销相当大。

    非对称加密算法的主要优势就是使用两个而不是一个密钥值:一个密钥值用来加密消息,另一个密钥值用来解密消息。这两个密钥值在同一个过程中生成,称为密钥对。用来加密消息的密钥称为公钥,用来解密消息的密钥称为私钥。用公钥加密的消息只能用与之对应的私钥来解密,私钥除了持有者外无人知道,而公钥却可通过非安全管道来发送或在目录中发布。

    Alice需要通过电子邮件给Bob发送一个机密文档。首先,Bob使用电子邮件将自己的公钥发送给Alice。然后Alice用Bob的公钥对文档加密并通过电子邮件将加密消息发送给Bob。由于任何用Bob 的公钥加密的消息只能用Bob的私钥解密,因此即使窥探者知道Bob的公钥,消息也仍是安全的。Bob在收到加密消息后,用自己的私钥进行解密从而恢复原始文档。

                                                  Base64加密算法

    Base64加密后进行GZIP压缩处理,获得明文,安全性得到了保证。

    简介

      标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。

      为解决此问题,可采用一种用于URL的改进Base64编码,它不在末尾填充'='号,并将标 准Base64中的“+”和“/”分别改成了“*”和“-”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增 加,并统一了数据库、表单等处对象标识符的格式。

      另有一种用于正则表达式的改进Base64变种,它将“+”和“/”改成了“!”和“-”,因为“+”,“*”以及前面在IRCu中用到的“[”和“]”在正则表达式中都可能具有特殊含义。

      此外还有一些变种,它们将“+/”改为“_-”或“._”(用作编程语言中的标识符名称)或“.-”(用于XML中的Nmtoken)甚至“_:”(用于XML中的Name)。

      Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。

    规则

      关于这个编码的规则:

      ①.把3个字符变成4个字符..

      ②每76个字符加一个换行符..

      ③.最后的结束符也要处理..

      这样说会不会太抽象了?不怕,我们来看一个例子:

      转换前 aaaaaabb ccccdddd eeffffff

      转换后 00aaaaaa 00bbcccc 00ddddee 00ffffff

      应该很清楚了吧?上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0。

      转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:(摘自RFC2045)

    转换表  

    索引

    对应字符

    索引

    对应字符

    索引

    对应字符

    索引

    对应字符

    0

    A

    17

    R

    34

    i

    51

    z

    1

    B

    18

    S

    35

    j

    52

    0

    2

    C

    19

    T

    36

    k

    53

    1

    3

    D

    20

    U

    37

    l

    54

    2

    4

    E

    21

    V

    38

    m

    55

    3

    5

    F

    22

    W

    39

    n

    56

    4

    6

    G

    23

    X

    40

    o

    57

    5

    7

    H

    24

    Y

    41

    p

    58

    6

    8

    I

    25

    Z

    42

    q

    59

    7

    9

    J

    26

    a

    43

    r

    60

    8

    10

    K

    27

    b

    44

    s

    61

    9

    11

    L

    28

    c

    45

    t

    62

    +

    12

    M

    29

    d

    46

    u

    63

    /

    13

    N

    30

    e

    47

    v

     

     

    14

    O

    31

    f

    48

    w

     

     

    15

    P

    32

    g

    49

    x

     

     

    16

    Q

    33

    h

    50

    y

    pad

    =

    举例

      让我们再来看一个实际的例子,加深印象!

      转换前 10101101 10111010 01110110

      转换后 00101011 00011011 00101001 00110110

      十进制 43 27 41 54

      对应码表中的值 r b p 2

      所以上面的24位编码,编码后的Base64值为rbp2

      解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。

      (解码只是编码的逆过程,在此我就不多说了,另外有关MIME的RFC还是有很多的,如果需要详细情况请自行查找。)

      用更接近于编程的思维来说,编码的过程是这样的:

      第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符。

      然后将第一个字符左移4位加上第二个字符右移4位,即获得第二个目标字符。

      再将第二个字符左移2位加上第三个字符右移6位,获得第三个目标字符。

      最后取第三个字符的右6位即获得第四个目标字符。

      在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。

      可是等等……聪明的你可能会问到,原文的字节数量应该是3的倍数啊,如果这个条件不能满足的话,那该怎么办呢?

      我们的解决办法是这样的:原文的字节不够的地方可以用全0来补足,转换时Base64编码用=号来代替。这就是为什么有些Base64编码会以一个或两个等号结束的原因,但等号最多只有两个。因为:

      余数 = 原文字节数 MOD 3

      所以余数任何情况下都只可能是0,1,2这三个数中的一个。如果余数是0的话,就表示原文字节数正好是3的倍数(最理想的情况啦)。如果是1的话,为了让Base64编码是3的倍数,就要补2个等号;同理,如果是2的话,就要补1个等号。


    各种下载软件地址

           先以“迅雷下载”为例: 很多下载类网站都提供“迅雷下载”的链接,其地址通常是加密的迅雷专用下载地址。

      如thunder://QUFodHRwOi8vd3d3LmJhaWR1LmNvbS9pbWcvc3NsbTFfbG9nby5naWZaWg==

      其实迅雷的“专用地址”也是用Base64加密的,其加密过程如下:

      一、在地址的前后分别添加AA和ZZ

      如www.baidu.com/img/sslm1_logo.gif变成

      AAwww.baidu.com/img/sslm1_logo.gifZZ

      二、对新的字符串进行Base64编码

      如AAwww.baidu.com/img/sslm1_logo.gifZZ用Base64编码得到

      QUF3d3cuYmFpZHUuY29tL2ltZy9zc2xtMV9sb2dvLmdpZlpa

      三、在上面得到的字符串前加上“thunder://”就成了

      thunder://QUF3d3cuYmFpZHUuY29tL2ltZy9zc2xtMV9sb2dvLmdpZlpa

      另:

      Flashget的与迅雷类似,只不过在第一步时加的“料”不同罢了,Flashget在地址前后加的“料”是[FLASHGET]

      而QQ旋风的干脆不加料,直接就对地址进行Base64编码了

    各语言实现方式

          php 

         [下列代码仅在GBK中实现,UTF8代码请把 if($button=="迅雷地址->普通地址") echosubstr(base64_decode(str_ireplace("thunder://","",$txt1)),2,-2);这句改为if($button=="迅雷地址->普通地址") echosubstr(mb_convert_encoding(base64_decode(str_ireplace("thunder://","",$txt1))),2,-2);并把charset=gb2312改为charset=utf-8]

    [php] view plain copy
    1. <?php   
    2.   $txt1=trim($_POST['text1']);   
    3.   $txt2=trim($_POST['text2']);   
    4.   $txt3=trim($_POST['text3']);   
    5.   $button=$_POST['button'];   
    6.   ?>   
    7.   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >   
    8.   <html>   
    9.   <head>   
    10.   <title>迅雷和FlashGet,QQ旋风地址 地址转换工具</title>   
    11.   <meta http-equiv="Content-Type" content="text/html; charset=gb2312">   
    12.   <meta content="迅雷,FlashGet,地址转换," name="keywords">   
    13.   </head>   
    14.   <body>   
    15.   <form name="form1" method="post" action="">   
    16.   <hr size="1">   
    17.   <h3>迅雷转换</h3>   
    18.   <P>转换地址:   
    19.   <input name="text1" value="<?php echo $txt1;?>" type="text" style="width:516px;" /></P>   
    20.   <P>转换后的:   
    21.   <input type="text" value="<?php   
    22.   if($button=="普通地址->迅雷地址"echo "thunder://".base64_encode("AA".$txt1."ZZ");   
    23.   if($button=="迅雷地址->普通地址"echo substr(base64_decode(str_ireplace("thunder://","",$txt1)),2,-2);   
    24.   ?>" style="width:516px;" /></P>   
    25.   <P>   
    26.   <input type="submit" name="button" value="普通地址->迅雷地址" />   
    27.   <input type="submit" name="button" value="迅雷地址->普通地址" /></P>   
    28.   <h3>FlashGet转换</h3>   
    29.   <P>FlashGet地址:   
    30.   <input name="text2" value="<?php echo $txt2;?>" type="text" style="width:516px;" /></P>   
    31.   <P>转换后 地址:   
    32.   <input type="text" value="<?php   
    33.   if($button=="普通地址->FlashGet地址"echo "flashget://".base64_encode($txt2);   
    34.   if($button=="FlashGet地址->普通地址"echo str_ireplace("[FLASHGET]","",base64_decode(str_ireplace("flashget://","",$txt2)));   
    35.   ?>" style="width:516px;" /></P>   
    36.   <P>   
    37.   <input type="submit" value="普通地址->FlashGet地址" name="button" />   
    38.   <input type="submit" value="FlashGet地址->普通地址" name="button" /></P>   
    39.   <h3>QQ旋风转换</h3>   
    40.   <P>QQ旋风地址:   
    41.   <input name="text3" value="<?php echo $txt3;?>" type="text" style="width:516px;" /></P>   
    42.   <P>转换后 地址:   
    43.   <input type="text" value="<?php   
    44.   if($button=="普通地址->QQ旋风"echo "qqdl://".base64_encode($txt3);   
    45.   if($button=="QQ旋风->普通地址"echo base64_decode(str_ireplace("qqdl://","",$txt3));   
    46.   ?>" style="width:516px;" /></P>   
    47.   <P>   
    48.   <input type="submit" value="普通地址->QQ旋风" name="button" />   
    49.   <input type="submit" value="QQ旋风->普通地址" name="button" /></P>   
    50.   </form>   
    51.   </body>   
    52.   </html>  

    VB

    [vb] view plain copy
    1. Option Explicit   
    2.   ' Base64 Encoding/Decoding Algorithm   
    3.   ' By: David Midkiff (mznull@earthlink.net)   
    4.     
    5.   ' This algorithms encodes and decodes data into Base64   
    6.   ' format. This format is extremely more efficient than   
    7.   ' Hexadecimal encoding.   
    8.   Private m_bytIndex(0 To 63) As Byte   
    9.   Private m_bytReverseIndex(0 To 255) As Byte   
    10.   Private Const k_bytEqualSign As Byte = 61   
    11.   Private Const k_bytMask1 As Byte = 3   
    12.   Private Const k_bytMask2 As Byte = 15   
    13.   Private Const k_bytMask3 As Byte = 63   
    14.   Private Const k_bytMask4 As Byte = 192   
    15.   Private Const k_bytMask5 As Byte = 240   
    16.   Private Const k_bytMask6 As Byte = 252   
    17.   Private Const k_bytShift2 As Byte = 4   
    18.   Private Const k_bytShift4 As Byte = 16   
    19.   Private Const k_bytShift6 As Byte = 64   
    20.   Private Const k_lMaxBytesPerLine As Long = 152   
    21.   Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As LongByVal Source As LongByVal Length As Long)   
    22.   Public Function Decode64(sInput As StringAs String   
    23.   If sInput = "" Then Exit Function   
    24.   Decode64 = StrConv(DecodeArray64(sInput), vbUnicode)   
    25.   End Function   
    26.   Private Function DecodeArray64(sInput As StringAs Byte()   
    27.   Dim bytInput() As Byte   
    28.   Dim bytWorkspace() As Byte   
    29.   Dim bytResult() As Byte   
    30.   Dim lInputCounter As Long   
    31.   Dim lWorkspaceCounter As Long   
    32.   bytInput = Replace(Replace(sInput, vbCrLf, ""), "=""")   
    33.   ReDim bytWorkspace(LBound(bytInput) To (UBound(bytInput) * 2)) As Byte   
    34.   lWorkspaceCounter = LBound(bytWorkspace)   
    35.   For lInputCounter = LBound(bytInput) To UBound(bytInput)   
    36.   bytInput(lInputCounter) = m_bytReverseIndex(bytInput(lInputCounter))   
    37.   Next lInputCounter   
    38.   For lInputCounter = LBound(bytInput) To (UBound(bytInput) - ((UBound(bytInput) Mod 8) + 8)) Step 8   
    39.   bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2) \ k_bytShift4)   
    40.   bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytMask2) * k_bytShift4) + (bytInput(lInputCounter + 4) \ k_bytShift2)   
    41.   bytWorkspace(lWorkspaceCounter + 2) = ((bytInput(lInputCounter + 4) And k_bytMask1) * k_bytShift6) + bytInput(lInputCounter + 6)   
    42.   lWorkspaceCounter = lWorkspaceCounter + 3   
    43.   Next lInputCounter   
    44.   Select Case (UBound(bytInput) Mod 8):   
    45.   Case 3:   
    46.   bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2) \ k_bytShift4)   
    47.   Case 5:   
    48.   bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2) \ k_bytShift4)   
    49.   bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytMask2) * k_bytShift4) + (bytInput(lInputCounter + 4) \ k_bytShift2)   
    50.   lWorkspaceCounter = lWorkspaceCounter + 1   
    51.   Case 7:   
    52.   bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2) \ k_bytShift4)   
    53.   bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytMask2) * k_bytShift4) + (bytInput(lInputCounter + 4) \ k_bytShift2)   
    54.   bytWorkspace(lWorkspaceCounter + 2) = ((bytInput(lInputCounter + 4) And k_bytMask1) * k_bytShift6) + bytInput(lInputCounter + 6)   
    55.   lWorkspaceCounter = lWorkspaceCounter + 2   
    56.   End Select   
    57.   ReDim bytResult(LBound(bytWorkspace) To lWorkspaceCounter) As Byte   
    58.   If LBound(bytWorkspace) = 0 Then lWorkspaceCounter = lWorkspaceCounter + 1   
    59.   CopyMemory VarPtr(bytResult(LBound(bytResult))), VarPtr(bytWorkspace(LBound(bytWorkspace))), lWorkspaceCounter   
    60.   DecodeArray64 = bytResult   
    61.   End Function   
    62.   Public Function Encode64(ByRef sInput As StringAs String   
    63.   If sInput = "" Then Exit Function   
    64.   Dim bytTemp() As Byte   
    65.   bytTemp = StrConv(sInput, vbFromUnicode)   
    66.   Encode64 = EncodeArray64(bytTemp)   
    67.   End Function   
    68.   Private Function EncodeArray64(ByRef bytInput() As ByteAs String   
    69.   On Error GoTo ErrorHandler   
    70.   Dim bytWorkspace() As Byte, bytResult() As Byte   
    71.   Dim bytCrLf(0 To 3) As Byte, lCounter As Long   
    72.   Dim lWorkspaceCounter As Long, lLineCounter As Long   
    73.   Dim lCompleteLines As Long, lBytesRemaining As Long   
    74.   Dim lpWorkSpace As Long, lpResult As Long   
    75.   Dim lpCrLf As Long   
    76.   If UBound(bytInput) < 1024 Then   
    77.   ReDim bytWorkspace(LBound(bytInput) To (LBound(bytInput) + 4096)) As Byte   
    78.   Else   
    79.   ReDim bytWorkspace(LBound(bytInput) To (UBound(bytInput) * 4)) As Byte   
    80.   End If   
    81.   lWorkspaceCounter = LBound(bytWorkspace)   
    82.   For lCounter = LBound(bytInput) To (UBound(bytInput) - ((UBound(bytInput) Mod 3) + 3)) Step 3   
    83.   bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter) \ k_bytShift2))   
    84.   bytWorkspace(lWorkspaceCounter + 2) = m_bytIndex(((bytInput(lCounter) And k_bytMask1) * k_bytShift4) + ((bytInput(lCounter + 1)) \ k_bytShift4))   
    85.   bytWorkspace(lWorkspaceCounter + 4) = m_bytIndex(((bytInput(lCounter + 1) And k_bytMask2) * k_bytShift2) + (bytInput(lCounter + 2) \ k_bytShift6))   
    86.   bytWorkspace(lWorkspaceCounter + 6) = m_bytIndex(bytInput(lCounter + 2) And k_bytMask3)   
    87.   lWorkspaceCounter = lWorkspaceCounter + 8   
    88.   Next lCounter   
    89.   Select Case (UBound(bytInput) Mod 3):   
    90.   Case 0:   
    91.   bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter) \ k_bytShift2))   
    92.   bytWorkspace(lWorkspaceCounter + 2) = m_bytIndex((bytInput(lCounter) And k_bytMask1) * k_bytShift4)   
    93.   bytWorkspace(lWorkspaceCounter + 4) = k_bytEqualSign   
    94.   bytWorkspace(lWorkspaceCounter + 6) = k_bytEqualSign   
    95.   Case 1:   
    96.   bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter) \ k_bytShift2))   
    97.   bytWorkspace(lWorkspaceCounter + 2) = m_bytIndex(((bytInput(lCounter) And k_bytMask1) * k_bytShift4) + ((bytInput(lCounter + 1)) \ k_bytShift4))   
    98.   bytWorkspace(lWorkspaceCounter + 4) = m_bytIndex((bytInput(lCounter + 1) And k_bytMask2) * k_bytShift2)   
    99.   bytWorkspace(lWorkspaceCounter + 6) = k_bytEqualSign   
    100.   Case 2:   
    101.   bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter) \ k_bytShift2))   
    102.   bytWorkspace(lWorkspaceCounter + 2) = m_bytIndex(((bytInput(lCounter) And k_bytMask1) * k_bytShift4) + ((bytInput(lCounter + 1)) \ k_bytShift4))   
    103.   bytWorkspace(lWorkspaceCounter + 4) = m_bytIndex(((bytInput(lCounter + 1) And k_bytMask2) * k_bytShift2) + ((bytInput(lCounter + 2)) \ k_bytShift6))   
    104.   bytWorkspace(lWorkspaceCounter + 6) = m_bytIndex(bytInput(lCounter + 2) And k_bytMask3)   
    105.   End Select   
    106.   lWorkspaceCounter = lWorkspaceCounter + 8   
    107.   If lWorkspaceCounter <= k_lMaxBytesPerLine Then   
    108.   EncodeArray64 = Left$(bytWorkspace, InStr(1, bytWorkspace, Chr$(0)) - 1)   
    109.   Else   
    110.   bytCrLf(0) = 13   
    111.   bytCrLf(1) = 0   
    112.   bytCrLf(2) = 10   
    113.   bytCrLf(3) = 0   
    114.   ReDim bytResult(LBound(bytWorkspace) To UBound(bytWorkspace))   
    115.   lpWorkSpace = VarPtr(bytWorkspace(LBound(bytWorkspace)))   
    116.   lpResult = VarPtr(bytResult(LBound(bytResult)))   
    117.   lpCrLf = VarPtr(bytCrLf(LBound(bytCrLf)))   
    118.   lCompleteLines = Fix(lWorkspaceCounter / k_lMaxBytesPerLine)   
    119.   For lLineCounter = 0 To lCompleteLines   
    120.   CopyMemory lpResult, lpWorkSpace, k_lMaxBytesPerLine   
    121.   lpWorkSpace = lpWorkSpace + k_lMaxBytesPerLine   
    122.   lpResult = lpResult + k_lMaxBytesPerLine   
    123.   CopyMemory lpResult, lpCrLf, 4&   
    124.   lpResult = lpResult + 4&   
    125.   Next lLineCounter   
    126.   lBytesRemaining = lWorkspaceCounter - (lCompleteLines * k_lMaxBytesPerLine)   
    127.   If lBytesRemaining > 0 Then CopyMemory lpResult, lpWorkSpace, lBytesRemaining   
    128.   EncodeArray64 = Left$(bytResult, InStr(1, bytResult, Chr$(0)) - 1)   
    129.   End If   
    130.   Exit Function   
    131.   ErrorHandler:   
    132.   Erase bytResult   
    133.   EncodeArray64 = bytResult   
    134.   End Function   
    135.   Private Sub Class_Initialize()   
    136.   m_bytIndex(0) = 65 'Asc("A")   
    137.   m_bytIndex(1) = 66 'Asc("B")   
    138.   m_bytIndex(2) = 67 'Asc("C")   
    139.   m_bytIndex(3) = 68 'Asc("D")   
    140.   m_bytIndex(4) = 69 'Asc("E")   
    141.   m_bytIndex(5) = 70 'Asc("F")   
    142.   m_bytIndex(6) = 71 'Asc("G")   
    143.   m_bytIndex(7) = 72 'Asc("H")   
    144.   m_bytIndex(8) = 73 'Asc("I")   
    145.   m_bytIndex(9) = 74 'Asc("J")   
    146.   m_bytIndex(10) = 75 'Asc("K")   
    147.   m_bytIndex(11) = 76 'Asc("L")   
    148.   m_bytIndex(12) = 77 'Asc("M")   
    149.   m_bytIndex(13) = 78 'Asc("N")   
    150.   m_bytIndex(14) = 79 'Asc("O")   
    151.   m_bytIndex(15) = 80 'Asc("P")   
    152.   m_bytIndex(16) = 81 'Asc("Q")   
    153.   m_bytIndex(17) = 82 'Asc("R")   
    154.   m_bytIndex(18) = 83 'Asc("S")   
    155.   m_bytIndex(19) = 84 'Asc("T")   
    156.   m_bytIndex(20) = 85 'Asc("U")   
    157.   m_bytIndex(21) = 86 'Asc("V")   
    158.   m_bytIndex(22) = 87 'Asc("W")   
    159.   m_bytIndex(23) = 88 'Asc("X")   
    160.   m_bytIndex(24) = 89 'Asc("Y")   
    161.   m_bytIndex(25) = 90 'Asc("Z")   
    162.   m_bytIndex(26) = 97 'Asc("a")   
    163.   m_bytIndex(27) = 98 'Asc("b")   
    164.   m_bytIndex(28) = 99 'Asc("c")   
    165.   m_bytIndex(29) = 100 'Asc("d")   
    166.   m_bytIndex(30) = 101 'Asc("e")   
    167.   m_bytIndex(31) = 102 'Asc("f")   
    168.   m_bytIndex(32) = 103 'Asc("g")   
    169.   m_bytIndex(33) = 104 'Asc("h")   
    170.   m_bytIndex(34) = 105 'Asc("i")   
    171.   m_bytIndex(35) = 106 'Asc("j")   
    172.   m_bytIndex(36) = 107 'Asc("k")   
    173.   m_bytIndex(37) = 108 'Asc("l")   
    174.   m_bytIndex(38) = 109 'Asc("m")   
    175.   m_bytIndex(39) = 110 'Asc("n")   
    176.   m_bytIndex(40) = 111 'Asc("o")   
    177.   m_bytIndex(41) = 112 'Asc("p")   
    178.   m_bytIndex(42) = 113 'Asc("q")   
    179.   m_bytIndex(43) = 114 'Asc("r")   
    180.   m_bytIndex(44) = 115 'Asc("s")   
    181.   m_bytIndex(45) = 116 'Asc("t")   
    182.   m_bytIndex(46) = 117 'Asc("u")   
    183.   m_bytIndex(47) = 118 'Asc("v")   
    184.   m_bytIndex(48) = 119 'Asc("w")   
    185.   m_bytIndex(49) = 120 'Asc("x")   
    186.   m_bytIndex(50) = 121 'Asc("y")   
    187.   m_bytIndex(51) = 122 'Asc("z")   
    188.   m_bytIndex(52) = 48 'Asc("0")   
    189.   m_bytIndex(53) = 49 'Asc("1")   
    190.   m_bytIndex(54) = 50 'Asc("2")   
    191.   m_bytIndex(55) = 51 'Asc("3")   
    192.   m_bytIndex(56) = 52 'Asc("4")   
    193.   m_bytIndex(57) = 53 'Asc("5")   
    194.   m_bytIndex(58) = 54 'Asc("6")   
    195.   m_bytIndex(59) = 55 'Asc("7")   
    196.   m_bytIndex(60) = 56 'Asc("8")   
    197.   m_bytIndex(61) = 57 'Asc("9")   
    198.   m_bytIndex(62) = 43 'Asc("+")   
    199.   m_bytIndex(63) = 47 'Asc("/")   
    200.   m_bytReverseIndex(65) = 0 'Asc("A")   
    201.   m_bytReverseIndex(66) = 1 'Asc("B")   
    202.   m_bytReverseIndex(67) = 2 'Asc("C")   
    203.   m_bytReverseIndex(68) = 3 'Asc("D")   
    204.   m_bytReverseIndex(69) = 4 'Asc("E")   
    205.   m_bytReverseIndex(70) = 5 'Asc("F")   
    206.   m_bytReverseIndex(71) = 6 'Asc("G")   
    207.   m_bytReverseIndex(72) = 7 'Asc("H")   
    208.   m_bytReverseIndex(73) = 8 'Asc("I")   
    209.   m_bytReverseIndex(74) = 9 'Asc("J")   
    210.   m_bytReverseIndex(75) = 10 'Asc("K")   
    211.   m_bytReverseIndex(76) = 11 'Asc("L")   
    212.   m_bytReverseIndex(77) = 12 'Asc("M")   
    213.   m_bytReverseIndex(78) = 13 'Asc("N")   
    214.   m_bytReverseIndex(79) = 14 'Asc("O")   
    215.   m_bytReverseIndex(80) = 15 'Asc("P")   
    216.   m_bytReverseIndex(81) = 16 'Asc("Q")   
    217.   m_bytReverseIndex(82) = 17 'Asc("R")   
    218.   m_bytReverseIndex(83) = 18 'Asc("S")   
    219.   m_bytReverseIndex(84) = 19 'Asc("T")   
    220.   m_bytReverseIndex(85) = 20 'Asc("U")   
    221.   m_bytReverseIndex(86) = 21 'Asc("V")   
    222.   m_bytReverseIndex(87) = 22 'Asc("W")   
    223.   m_bytReverseIndex(88) = 23 'Asc("X")   
    224.   m_bytReverseIndex(89) = 24 'Asc("Y")   
    225.   m_bytReverseIndex(90) = 25 'Asc("Z")   
    226.   m_bytReverseIndex(97) = 26 'Asc("a")   
    227.   m_bytReverseIndex(98) = 27 'Asc("b")   
    228.   m_bytReverseIndex(99) = 28 'Asc("c")   
    229.   m_bytReverseIndex(100) = 29 'Asc("d")   
    230.   m_bytReverseIndex(101) = 30 'Asc("e")   
    231.   m_bytReverseIndex(102) = 31 'Asc("f")   
    232.   m_bytReverseIndex(103) = 32 'Asc("g")   
    233.   m_bytReverseIndex(104) = 33 'Asc("h")   
    234.   m_bytReverseIndex(105) = 34 'Asc("i")   
    235.   m_bytReverseIndex(106) = 35 'Asc("j")   
    236.   m_bytReverseIndex(107) = 36 'Asc("k")   
    237.   m_bytReverseIndex(108) = 37 'Asc("l")   
    238.   m_bytReverseIndex(109) = 38 'Asc("m")   
    239.   m_bytReverseIndex(110) = 39 'Asc("n")   
    240.   m_bytReverseIndex(111) = 40 'Asc("o")   
    241.   m_bytReverseIndex(112) = 41 'Asc("p")   
    242.   m_bytReverseIndex(113) = 42 'Asc("q")   
    243.   m_bytReverseIndex(114) = 43 'Asc("r")   
    244.   m_bytReverseIndex(115) = 44 'Asc("s")   
    245.   m_bytReverseIndex(116) = 45 'Asc("t")   
    246.   m_bytReverseIndex(117) = 46 'Asc("u")   
    247.   m_bytReverseIndex(118) = 47 'Asc("v")   
    248.   m_bytReverseIndex(119) = 48 'Asc("w")   
    249.   m_bytReverseIndex(120) = 49 'Asc("x")   
    250.   m_bytReverseIndex(121) = 50 'Asc("y")   
    251.   m_bytReverseIndex(122) = 51 'Asc("z")   
    252.   m_bytReverseIndex(48) = 52 'Asc("0")   
    253.   m_bytReverseIndex(49) = 53 'Asc("1")   
    254.   m_bytReverseIndex(50) = 54 'Asc("2")   
    255.   m_bytReverseIndex(51) = 55 'Asc("3")   
    256.   m_bytReverseIndex(52) = 56 'Asc("4")   
    257.   m_bytReverseIndex(53) = 57 'Asc("5")   
    258.   m_bytReverseIndex(54) = 58 'Asc("6")   
    259.   m_bytReverseIndex(55) = 59 'Asc("7")   
    260.   m_bytReverseIndex(56) = 60 'Asc("8")   
    261.   m_bytReverseIndex(57) = 61 'Asc("9")   
    262.   m_bytReverseIndex(43) = 62 'Asc("+")   
    263.   m_bytReverseIndex(47) = 63 'Asc("/")   
    264.   End Sub  

    JS

    [javascript] view plain copy
    1. var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";   
    2.   var base64DecodeChars = new Array(   
    3.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,   
    4.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,   
    5.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,   
    6.   52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,   
    7.   -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,   
    8.   15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,   
    9.   -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,   
    10.   41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);   
    11.   function base64encode(str)   
    12.   {   
    13.   var returnVal, i, len;   
    14.   var c1, c2, c3;   
    15.   len = str.length;   
    16.   i = 0;   
    17.   returnVal = "";   
    18.   while(i < len)   
    19.   {   
    20.   c1 = str.charCodeAt(i++) & 0xff;   
    21.   if(i == len)   
    22.   {   
    23.   returnVal += base64EncodeChars.charAt(c1 >> 2);   
    24.   returnVal += base64EncodeChars.charAt((c1 & 0x3) << 4);   
    25.   returnVal += "==";   
    26.   break;   
    27.   }   
    28.   c2 = str.charCodeAt(i++);   
    29.   if(i == len)   
    30.   {   
    31.   returnVal += base64EncodeChars.charAt(c1 >> 2);   
    32.   returnVal += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));   
    33.   returnVal += base64EncodeChars.charAt((c2 & 0xF) << 2);   
    34.   returnVal += "=";   
    35.   break;   
    36.   }   
    37.   c3 = str.charCodeAt(i++);   
    38.   returnVal += base64EncodeChars.charAt(c1 >> 2);   
    39.   returnVal += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));   
    40.   returnVal += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));   
    41.   returnVal += base64EncodeChars.charAt(c3 & 0x3F);   
    42.   }   
    43.   return returnVal;   
    44.   }   
    45.   function base64decode(str)   
    46.   {   
    47.   var c1, c2, c3, c4;   
    48.   var i, len, returnVal;   
    49.   len = str.length;   
    50.   i = 0;   
    51.   returnVal = "";   
    52.   while(i < len)   
    53.   {   
    54.   /* c1 */   
    55.   do   
    56.   {   
    57.   c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];   
    58.   } while(i < len && c1 == -1);   
    59.   if(c1 == -1)   
    60.   break;   
    61.   /* c2 */   
    62.   do   
    63.   {   
    64.   c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];   
    65.   } while(i < len && c2 == -1);   
    66.   if(c2 == -1)   
    67.   break;   
    68.   returnVal += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));   
    69.   /* c3 */   
    70.   do   
    71.   {   
    72.   c3 = str.charCodeAt(i++) & 0xff;   
    73.   if(c3 == 61)   
    74.   return returnVal;   
    75.   c3 = base64DecodeChars[c3];   
    76.   } while(i < len && c3 == -1);   
    77.   if(c3 == -1)   
    78.   break;   
    79.   returnVal += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));   
    80.   /* c4 */   
    81.   do   
    82.   {   
    83.   c4 = str.charCodeAt(i++) & 0xff;   
    84.   if(c4 == 61)   
    85.   return returnVal;   
    86.   c4 = base64DecodeChars[c4];   
    87.   } while(i < len && c4 == -1);   
    88.   if(c4 == -1)   
    89.   break;   
    90.   returnVal += String.fromCharCode(((c3 & 0x03) << 6) | c4);   
    91.   }   
    92.   return returnVal;   
    93.   }   

    AS

    [plain] view plain copy
    1. package crypto{   
    2.   import flash.utils.ByteArray;   
    3.   public class Base64 {   
    4.   private static const BASE64_CHARS:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";   
    5.   public static function encode(data:String):String {   
    6.   // Convert string to ByteArray   
    7.   var bytes:ByteArray = new ByteArray();   
    8.   bytes.writeUTFBytes(data);   
    9.   // Return encoded ByteArray   
    10.   return encodeByteArray(bytes);   
    11.   }   
    12.   public static function encodeByteArray(data:ByteArray):String {   
    13.   // Initialise output   
    14.   var output:String = "";   
    15.   // Create data and output buffers   
    16.   var dataBuffer:Array;   
    17.   var outputBuffer:Array = new Array(4);   
    18.   // Rewind ByteArray   
    19.   data.position = 0;   
    20.   // while there are still bytes to be processed   
    21.   while (data.bytesAvailable > 0) {   
    22.   // Create new data buffer and populate next 3 bytes from data   
    23.   dataBuffer = new Array();   
    24.   for (var i:uint = 0; i < 3 && data.bytesAvailable > 0; i++) {   
    25.   dataBuffer= data.readUnsignedByte();   
    26.   }   
    27.   // Convert to data buffer Base64 character positions and   
    28.   // store in output buffer   
    29.   outputBuffer[0] = (dataBuffer[0] & 0xfc) >> 2;   
    30.   outputBuffer[1] = ((dataBuffer[0] & 0x03) << 4) | ((dataBuffer[1]) >> 4);   
    31.   outputBuffer[2] = ((dataBuffer[1] & 0x0f) << 2) | ((dataBuffer[2]) >> 6);   
    32.   outputBuffer[3] = dataBuffer[2] & 0x3f;   
    33.   // If data buffer was short (i.e not 3 characters) then set   
    34.   // end character indexes in data buffer to index of '=' symbol.   
    35.   // This is necessary because Base64 data is always a multiple of   
    36.   // 4 bytes and is basses with '=' symbols.   
    37.   for (var j:uint = dataBuffer.length; j < 3; j++) {   
    38.   outputBuffer[j + 1] = 64;   
    39.   }   
    40.   // Loop through output buffer and add Base64 characters to   
    41.   // encoded data string for each character.   
    42.   for (var k:uint = 0; k < outputBuffer.length; k++) {   
    43.   output += BASE64_CHARS.charAt(outputBuffer[k]);   
    44.   }   
    45.   }   
    46.   // Return encoded data   
    47.   return output;   
    48.   }   
    49.   public static function decode(data:String):String {   
    50.   // Decode data to ByteArray   
    51.   var bytes:ByteArray = decodeToByteArray(data);   
    52.   // Convert to string and return   
    53.   return bytes.readUTFBytes(bytes.length);   
    54.   }   
    55.   public static function decodeToByteArray(data:String):ByteArray {   
    56.   // Initialise output ByteArray for decoded data   
    57.   var output:ByteArray = new ByteArray();   
    58.   // Create data and output buffers   
    59.   var dataBuffer:Array = new Array(4);   
    60.   var outputBuffer:Array = new Array(3);   
    61.   // While there are data bytes left to be processed   
    62.   for (var i:uint = 0; i < data.length; i += 4) {   
    63.   // Populate data buffer with position of Base64 characters for   
    64.   // next 4 bytes from encoded data   
    65.   for (var j:uint = 0; j < 4 && i + j < data.length; j++) {   
    66.   dataBuffer[j] = BASE64_CHARS.indexOf(data.charAt(i + j));   
    67.   }   
    68.   // Decode data buffer back into bytes   
    69.   outputBuffer[0] = (dataBuffer[0] << 2) + ((dataBuffer[1] & 0x30) >> 4);   
    70.   outputBuffer[1] = ((dataBuffer[1] & 0x0f) << 4) + ((dataBuffer[2] & 0x3c) >> 2);   
    71.   outputBuffer[2] = ((dataBuffer[2] & 0x03) << 6) + dataBuffer[3];   
    72.   // Add all non-padded bytes in output buffer to decoded data   
    73.   for (var k:uint = 0; k < outputBuffer.length; k++) {   
    74.   if (dataBuffer[k+1] == 64) break;   
    75.   output.writeByte(outputBuffer[k]);   
    76.   }   
    77.   }   
    78.   // Rewind decoded data ByteArray   
    79.   output.position = 0;   
    80.   // Return decoded data   
    81.   return output;   
    82.   }   
    83.   public function Base64() {   
    84.   throw new Error("Base64 class is static container only");   
    85.   }   
    86.   }   
    87.   }   

    C#

    方法一:自己写实现过程

    [csharp] view plain copy
    1. /// <summary>   
    2.   /// Base64加密   
    3.   /// </summary>   
    4.   /// <param name="Message"></param>   
    5.   /// <returns></returns>   
    6.   public string Base64Code(string Message)   
    7.   {   
    8.   char[] Base64Code = new char[]{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T',   
    9.   'U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n',   
    10.   'o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7',   
    11.   '8','9','+','/','='};   
    12.   byte empty = (byte)0;   
    13.   System.Collections.ArrayList byteMessage = new System.Collections.ArrayList(System.Text.Encoding.Default.GetBytes(Message));   
    14.   System.Text.StringBuilder outmessage;   
    15.   int messageLen = byteMessage.Count;   
    16.   //将字符分成3个字节一组,如果不足,则以0补齐   
    17.   int page = messageLen / 3;   
    18.   int use = 0;   
    19.   if ((use = messageLen % 3) > 0)   
    20.   {   
    21.   for (int i = 0; i < 3 - use; i++)   
    22.   byteMessage.Add(empty);   
    23.   page++;   
    24.   }   
    25.   //将3个字节的每组字符转换成4个字节一组的。3个一组,一组一组变成4个字节一组   
    26.   //方法是:转换成ASCII码,按顺序排列24 位数据,再把这24位数据分成4组,即每组6位。再在每组的的最高位前补两个0凑足一个字节。   
    27.   outmessage = new System.Text.StringBuilder(page * 4);   
    28.   for (int i = 0; i < page; i++)   
    29.   {   
    30.   //取一组3个字节的组   
    31.   byte[] instr = new byte[3];   
    32.   instr[0] = (byte)byteMessage[i * 3];   
    33.   instr[1] = (byte)byteMessage[i * 3 + 1];   
    34.   instr[2] = (byte)byteMessage[i * 3 + 2];   
    35.   //六个位为一组,补0变成4个字节   
    36.   int[] outstr = new int[4];   
    37.   //第一个输出字节:取第一输入字节的前6位,并且在高位补0,使其变成8位(一个字节)   
    38.   outstr[0] = instr[0] >> 2;   
    39.   //第二个输出字节:取第一输入字节的后2位和第二个输入字节的前4位(共6位),并且在高位补0,使其变成8位(一个字节)   
    40.   outstr[1] = ((instr[0] & 0x03) << 4) ^ (instr[1] >> 4);   
    41.   //第三个输出字节:取第二输入字节的后4位和第三个输入字节的前2位(共6位),并且在高位补0,使其变成8位(一个字节)   
    42.   if (!instr[1].Equals(empty))   
    43.   outstr[2] = ((instr[1] & 0x0f) << 2) ^ (instr[2] >> 6);   
    44.   else   
    45.   outstr[2] = 64;   
    46.   //第四个输出字节:取第三输入字节的后6位,并且在高位补0,使其变成8位(一个字节)   
    47.   if (!instr[2].Equals(empty))   
    48.   outstr[3] = (instr[2] & 0x3f);   
    49.   else   
    50.   outstr[3] = 64;   
    51.   outmessage.Append(Base64Code[outstr[0]]);   
    52.   outmessage.Append(Base64Code[outstr[1]]);   
    53.   outmessage.Append(Base64Code[outstr[2]]);   
    54.   outmessage.Append(Base64Code[outstr[3]]);   
    55.   }   
    56.   return outmessage.ToString();   
    57.   }   
    58.   /// <summary>   
    59.   /// Base64解密   
    60.   /// </summary>   
    61.   /// <param name="Message"></param>   
    62.   /// <returns></returns>   
    63.   public string Base64Decode(string Message)   
    64.   {   
    65.   if ((Message.Length % 4) != 0)   
    66.   {   
    67.   throw new ArgumentException("不是正确的BASE64编码,请检查。""Message");   
    68.   }   
    69.   if (!System.Text.RegularExpressions.Regex.IsMatch(Message, "^[A-Z0-9/+=]*$", System.Text.RegularExpressions.RegexOptions.IgnoreCase))   
    70.   {   
    71.   throw new ArgumentException("包含不正确的BASE64编码,请检查。""Message");   
    72.   }   
    73.   string Base64Code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";   
    74.   int page = Message.Length / 4;   
    75.   System.Collections.ArrayList outMessage = new System.Collections.ArrayList(page * 3);   
    76.   char[] message = Message.ToCharArray();   
    77.   for (int i = 0; i < page; i++)   
    78.   {   
    79.   byte[] instr = new byte[4];   
    80.   instr[0] = (byte)Base64Code.IndexOf(message[i * 4]);   
    81.   instr[1] = (byte)Base64Code.IndexOf(message[i * 4 + 1]);   
    82.   instr[2] = (byte)Base64Code.IndexOf(message[i * 4 + 2]);   
    83.   instr[3] = (byte)Base64Code.IndexOf(message[i * 4 + 3]);   
    84.   byte[] outstr = new byte[3];   
    85.   outstr[0] = (byte)((instr[0] << 2) ^ ((instr[1] & 0x30) >> 4));   
    86.   if (instr[2] != 64)   
    87.   {   
    88.   outstr[1] = (byte)((instr[1] << 4) ^ ((instr[2] & 0x3c) >> 2));   
    89.   }   
    90.   else   
    91.   {   
    92.   outstr[2] = 0;   
    93.   }   
    94.   if (instr[3] != 64)   
    95.   {   
    96.   outstr[2] = (byte)((instr[2] << 6) ^ instr[3]);   
    97.   }   
    98.   else   
    99.   {   
    100.   outstr[2] = 0;   
    101.   }   
    102.   outMessage.Add(outstr[0]);   
    103.   if (outstr[1] != 0)   
    104.   outMessage.Add(outstr[1]);   
    105.   if (outstr[2] != 0)   
    106.   outMessage.Add(outstr[2]);   
    107.   }   
    108.   byte[] outbyte = (byte[])outMessage.ToArray(Type.GetType("System.Byte"));   
    109.   return System.Text.Encoding.Default.GetString(outbyte);   
    110.   }  

    方法二:直接调用。net中的类库

    [csharp] view plain copy
    1. /// <summary>   
    2.   /// Base64加密   
    3.   /// </summary>   
    4.   /// <param name="Message"></param>   
    5.   /// <returns></returns>   
    6.   public string Base64Code(string Message)   
    7.   {   
    8.   byte[] bytes = Encoding.Default.GetBytes(Message);   
    9.   return Convert.ToBase64String(bytes);   
    10.   }   
    11.   /// <summary>   
    12.   /// Base64解密   
    13.   /// </summary>   
    14.   /// <param name="Message"></param>   
    15.   /// <returns></returns>   
    16.   public string Base64Decode(string Message)   
    17.   {   
    18.   byte[] bytes = Convert.FromBase64String(Message);   
    19.   return Encoding.Default.GetString(bytes);   
    20.   }  

    展开全文
  • java对称加密与非对称加密

    万次阅读 2017-11-26 22:25:49
    java对称加密与非对称加密加密方式大致分为两种,对称加密和非对称加密对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key)。非对称加密为数据的加密...

    java对称加密与非对称加密

    加密方式大致分为两种,对称加密和非对称加密。对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key)。非对称加密为数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥,公钥(public key)和私钥(private key)。私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。因此安全性大大提高。


    对称加密

    所谓对称加密算法即:加密和解密使用相同密钥的算法。常见的有DES、3DES、AES、PBE等加密算法,这几种算法安全性依次是逐渐增强的。

    DES加密

    DES是一种对称加密算法,是一种非常简便的加密算法,但是密钥长度比较短。DES加密算法出自IBM的研究,后来被美国政府正式采用,之后开始广泛流传,但是近些年使用越来越少,因为DES使用56位密钥,以现代计算能力,24小时内即可被破解。虽然如此,在某些简单应用中,我们还是可以使用DES加密算法.简单的DES加密算法实现:

    public class DESUtil {
    
        private static final String KEY_ALGORITHM = "DES";
        private static final String DEFAULT_CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";//默认的加密算法
    
        /**
         * DES 加密操作
         *
         * @param content 待加密内容
         * @param key 加密密钥
         * @return 返回Base64转码后的加密数据
         */
        public static String encrypt(String content, String key) {
            try {
                Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器
    
                byte[] byteContent = content.getBytes("utf-8");
    
                cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));// 初始化为加密模式的密码器
    
                byte[] result = cipher.doFinal(byteContent);// 加密
    
                return Base64.encodeBase64String(result);//通过Base64转码返回
            } catch (Exception ex) {
                Logger.getLogger(DESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        /**
         * DES 解密操作
         *
         * @param content
         * @param key
         * @return
         */
        public static String decrypt(String content, String key) {
    
            try {
                //实例化
                Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
    
                //使用密钥初始化,设置为解密模式
                cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
    
                //执行操作
                byte[] result = cipher.doFinal(Base64.decodeBase64(content));
    
                return new String(result, "utf-8");
            } catch (Exception ex) {
                Logger.getLogger(DESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        /**
         * 生成加密秘钥
         *
         * @return
         */
        private static SecretKeySpec getSecretKey(final String key) {
            //返回生成指定算法密钥生成器的 KeyGenerator 对象
            KeyGenerator kg = null;
    
            try {
                kg = KeyGenerator.getInstance(KEY_ALGORITHM);
    
                //DES 要求密钥长度为 56
                kg.init(56, new SecureRandom(key.getBytes()));
    
                //生成一个密钥
                SecretKey secretKey = kg.generateKey();
    
                return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为DES专用密钥
            } catch (NoSuchAlgorithmException ex) {
                Logger.getLogger(DESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        public static void main(String[] args) {
            String content = "hello,您好";
            String key = "sde@5f98H*^hsff%dfs$r344&df8543*er";
            System.out.println("content:" + content);
            String s1 = DESUtil.encrypt(content, key);
            System.out.println("s1:" + s1);
            System.out.println("s2:"+ DESUtil.decrypt(s1, key));
    
        }
    
    }

    3DES加密

    3DES是一种对称加密算法,在 DES 的基础上,使用三重数据加密算法,对数据进行加密,它相当于是对每个数据块应用三次 DES 加密算法。由于计算机运算能力的增强,原版 DES 密码的密钥长度变得容易被暴力破解;3DES 即是设计用来提供一种相对简单的方法,即通过增加 DES 的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法这样来说,破解的概率就小了很多。缺点由于使用了三重数据加密算法,可能会比较耗性能。简单的3DES加密算法实现:

    public class TripDESUtil {
    
        private static final String KEY_ALGORITHM = "DESede";
        private static final String DEFAULT_CIPHER_ALGORITHM = "DESede/ECB/PKCS5Padding";//默认的加密算法
    
        /**
         * DESede 加密操作
         *
         * @param content 待加密内容
         * @param key 加密密钥
         * @return 返回Base64转码后的加密数据
         */
        public static String encrypt(String content, String key) {
            try {
                Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器
    
                byte[] byteContent = content.getBytes("utf-8");
    
                cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));// 初始化为加密模式的密码器
    
                byte[] result = cipher.doFinal(byteContent);// 加密
    
                return Base64.encodeBase64String(result);//通过Base64转码返回
            } catch (Exception ex) {
                Logger.getLogger(TripDESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        /**
         * DESede 解密操作
         *
         * @param content
         * @param key
         * @return
         */
        public static String decrypt(String content, String key) {
    
            try {
                //实例化
                Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
    
                //使用密钥初始化,设置为解密模式
                cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
    
                //执行操作
                byte[] result = cipher.doFinal(Base64.decodeBase64(content));
    
                return new String(result, "utf-8");
            } catch (Exception ex) {
                Logger.getLogger(TripDESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        /**
         * 生成加密秘钥
         *
         * @return
         */
        private static SecretKeySpec getSecretKey(final String key) {
            //返回生成指定算法密钥生成器的 KeyGenerator 对象
            KeyGenerator kg = null;
    
            try {
                kg = KeyGenerator.getInstance(KEY_ALGORITHM);
    
                //DESede
                kg.init(new SecureRandom(key.getBytes()));
    
                //生成一个密钥
                SecretKey secretKey = kg.generateKey();
    
                return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为DESede专用密钥
            } catch (NoSuchAlgorithmException ex) {
                Logger.getLogger(TripDESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        public static void main(String[] args) {
            String content = "hello,您好";
            String key = "sde@5f98H*^hsff%dfs$r344&df8543*er";
            System.out.println("content:" + content);
            String s1 = TripDESUtil.encrypt(content, key);
            System.out.println("s1:" + s1);
            System.out.println("s2:"+ TripDESUtil.decrypt(s1, key));
    
        }
    
    }

    AES加密

    AES是一种对称加密算法,在 DES 的基础上,使用三重数据加密算法,对数据进行加密,它相当于是对每个数据块应用三次 DES 加密算法。由于计算机运算能力的增强,原版 DES 密码的密钥长度变得容易被暴力破解;3DES 即是设计用来提供一种相对简单的方法,即通过增加 DES 的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法这样来说,破解的概率就小了很多。缺点由于使用了三重数据加密算法,可能会比较耗性能。简单的AES加密算法实现:

    public class AESUtil {
    
        private static final String KEY_ALGORITHM = "AES";
        private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//默认的加密算法
    
        /**
         * AES 加密操作
         *
         * @param content 待加密内容
         * @param key 加密密钥
         * @return 返回Base64转码后的加密数据
         */
        public static String encrypt(String content, String key) {
            try {
                Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器
    
                byte[] byteContent = content.getBytes("utf-8");
    
                cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));// 初始化为加密模式的密码器
    
                byte[] result = cipher.doFinal(byteContent);// 加密
    
                return Base64.encodeBase64String(result);//通过Base64转码返回
            } catch (Exception ex) {
                Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        /**
         * AES 解密操作
         *
         * @param content
         * @param key
         * @return
         */
        public static String decrypt(String content, String key) {
    
            try {
                //实例化
                Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
    
                //使用密钥初始化,设置为解密模式
                cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
    
                //执行操作
                byte[] result = cipher.doFinal(Base64.decodeBase64(content));
    
                return new String(result, "utf-8");
            } catch (Exception ex) {
                Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        /**
         * 生成加密秘钥
         *
         * @return
         */
        private static SecretKeySpec getSecretKey(final String key) {
            //返回生成指定算法密钥生成器的 KeyGenerator 对象
            KeyGenerator kg = null;
    
            try {
                kg = KeyGenerator.getInstance(KEY_ALGORITHM);
    
                //AES 要求密钥长度为 128
                kg.init(128, new SecureRandom(key.getBytes()));
    
                //生成一个密钥
                SecretKey secretKey = kg.generateKey();
    
                return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥
            } catch (NoSuchAlgorithmException ex) {
                Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            return null;
        }
    
        public static void main(String[] args) {
            String content = "hello,您好";
            String key = "sde@5f98H*^hsff%dfs$r344&df8543*er";
            System.out.println("content:" + content);
            String s1 = AESUtil.encrypt(content, key);
            System.out.println("s1:" + s1);
            System.out.println("s2:"+AESUtil.decrypt(s1, key));
    
        }
    
    }
    

    非对称加密

    非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。一般公钥是公开的,私钥是自己保存。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。安全性相对对称加密来说更高,是一种高级加密方式。

    RSA加密

    RSA是一种非对称加密算法.RSA有两个密钥,一个是公开的,称为公开密钥;一个是私密的,称为私密密钥。公开密钥是对大众公开的,私密密钥是服务器私有的,两者不能互推得出。用公开密钥对数据进行加密,私密密钥可解密;私密密钥对数据加密,公开密钥可解密。速度较对称加密慢。简单的RSA加密算法实现:

    /**
     * <p>
     * RSA公钥/私钥/签名工具包
     * </p>
     * <p>
     * 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman)
     * </p>
     * <p>
     * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>
     * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>
     * 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全
     * </p>
     *
     * @author IceWee
     * @date 2012-4-26
     * @version 1.0
     */
    public class RSAUtils {
    
        /**
         * 加密算法RSA
         */
        public static final String KEY_ALGORITHM = "RSA";
    
        /**
         * 签名算法
         */
        public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
    
        /**
         * 获取公钥的key
         */
        private static final String PUBLIC_KEY = "RSAPublicKey";
    
        /**
         * 获取私钥的key
         */
        private static final String PRIVATE_KEY = "RSAPrivateKey";
    
        /**
         * RSA最大加密明文大小
         */
        private static final int MAX_ENCRYPT_BLOCK = 117;
    
        /**
         * RSA最大解密密文大小
         */
        private static final int MAX_DECRYPT_BLOCK = 128;
    
        /**
         * <p>
         * 生成密钥对(公钥和私钥)
         * </p>
         *
         * @return
         * @throws Exception
         */
        public static Map<String, Object> genKeyPair() throws Exception {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
            keyPairGen.initialize(1024);
            KeyPair keyPair = keyPairGen.generateKeyPair();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            Map<String, Object> keyMap = new HashMap<String, Object>(2);
            keyMap.put(PUBLIC_KEY, publicKey);
            keyMap.put(PRIVATE_KEY, privateKey);
            return keyMap;
        }
    
        /**
         * <p>
         * 用私钥对信息生成数字签名
         * </p>
         *
         * @param data 已加密数据
         * @param privateKey 私钥(BASE64编码)
         *
         * @return
         * @throws Exception
         */
        public static String sign(byte[] data, String privateKey) throws Exception {
            byte[] keyBytes = Base64Utils.decode(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initSign(privateK);
            signature.update(data);
            return Base64Utils.encode(signature.sign());
        }
    
        /**
         * <p>
         * 校验数字签名
         * </p>
         *
         * @param data 已加密数据
         * @param publicKey 公钥(BASE64编码)
         * @param sign 数字签名
         *
         * @return
         * @throws Exception
         *
         */
        public static boolean verify(byte[] data, String publicKey, String sign)
                throws Exception {
            byte[] keyBytes = Base64Utils.decode(publicKey);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PublicKey publicK = keyFactory.generatePublic(keySpec);
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initVerify(publicK);
            signature.update(data);
            return signature.verify(Base64Utils.decode(sign));
        }
    
        /**
         * <P>
         * 私钥解密
         * </p>
         *
         * @param encryptedData 已加密数据
         * @param privateKey 私钥(BASE64编码)
         * @return
         * @throws Exception
         */
        public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
                throws Exception {
            byte[] keyBytes = Base64Utils.decode(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateK);
            int inputLen = encryptedData.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            return decryptedData;
        }
    
        /**
         * <p>
         * 公钥解密
         * </p>
         *
         * @param encryptedData 已加密数据
         * @param publicKey 公钥(BASE64编码)
         * @return
         * @throws Exception
         */
        public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)
                throws Exception {
            byte[] keyBytes = Base64Utils.decode(publicKey);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key publicK = keyFactory.generatePublic(x509KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, publicK);
            int inputLen = encryptedData.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            return decryptedData;
        }
    
        /**
         * <p>
         * 公钥加密
         * </p>
         *
         * @param data 源数据
         * @param publicKey 公钥(BASE64编码)
         * @return
         * @throws Exception
         */
        public static byte[] encryptByPublicKey(byte[] data, String publicKey)
                throws Exception {
            byte[] keyBytes = Base64Utils.decode(publicKey);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key publicK = keyFactory.generatePublic(x509KeySpec);
            // 对数据加密
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicK);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            return encryptedData;
        }
    
        /**
         * <p>
         * 私钥加密
         * </p>
         *
         * @param data 源数据
         * @param privateKey 私钥(BASE64编码)
         * @return
         * @throws Exception
         */
        public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
                throws Exception {
            byte[] keyBytes = Base64Utils.decode(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, privateK);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            return encryptedData;
        }
    
        /**
         * <p>
         * 获取私钥
         * </p>
         *
         * @param keyMap 密钥对
         * @return
         * @throws Exception
         */
        public static String getPrivateKey(Map<String, Object> keyMap)
                throws Exception {
            Key key = (Key) keyMap.get(PRIVATE_KEY);
            return Base64Utils.encode(key.getEncoded());
        }
    
        /**
         * <p>
         * 获取公钥
         * </p>
         *
         * @param keyMap 密钥对
         * @return
         * @throws Exception
         */
        public static String getPublicKey(Map<String, Object> keyMap)
                throws Exception {
            Key key = (Key) keyMap.get(PUBLIC_KEY);
            return Base64Utils.encode(key.getEncoded());
        }
    
    }
    public class Base64Utils {
    
        /**
         * 文件读取缓冲区大小
         */
        private static final int CACHE_SIZE = 1024;
    
        /**
         * <p>
         * BASE64字符串解码为二进制数据
         * </p>
         *
         * @param base64
         * @return
         * @throws Exception
         */
        public static byte[] decode(String base64) throws Exception {
            return Base64.decode(base64.getBytes());
        }
    
        /**
         * <p>
         * 二进制数据编码为BASE64字符串
         * </p>
         *
         * @param bytes
         * @return
         * @throws Exception
         */
        public static String encode(byte[] bytes) throws Exception {
            return new String(Base64.encode(bytes));
        }
    
        /**
         * <p>
         * 将文件编码为BASE64字符串
         * </p>
         * <p>
         * 大文件慎用,可能会导致内存溢出
         * </p>
         *
         * @param filePath
         *            文件绝对路径
         * @return
         * @throws Exception
         */
        public static String encodeFile(String filePath) throws Exception {
            byte[] bytes = fileToByte(filePath);
            return encode(bytes);
        }
    
        /**
         * <p>
         * BASE64字符串转回文件
         * </p>
         *
         * @param filePath
         *            文件绝对路径
         * @param base64
         *            编码字符串
         * @throws Exception
         */
        public static void decodeToFile(String filePath, String base64) throws Exception {
            byte[] bytes = decode(base64);
            byteArrayToFile(bytes, filePath);
        }
    
        /**
         * <p>
         * 文件转换为二进制数组
         * </p>
         *
         * @param filePath
         *            文件路径
         * @return
         * @throws Exception
         */
        public static byte[] fileToByte(String filePath) throws Exception {
            byte[] data = new byte[0];
            File file = new File(filePath);
            if (file.exists()) {
                FileInputStream in = new FileInputStream(file);
                ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
                byte[] cache = new byte[CACHE_SIZE];
                int nRead = 0;
                while ((nRead = in.read(cache)) != -1) {
                    out.write(cache, 0, nRead);
                    out.flush();
                }
                out.close();
                in.close();
                data = out.toByteArray();
            }
            return data;
        }
    
        /**
         * <p>
         * 二进制数据写文件
         * </p>
         *
         * @param bytes
         *            二进制数据
         * @param filePath
         *            文件生成目录
         */
        public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
            InputStream in = new ByteArrayInputStream(bytes);
            File destFile = new File(filePath);
            if (!destFile.getParentFile().exists()) {
                destFile.getParentFile().mkdirs();
            }
            destFile.createNewFile();
            OutputStream out = new FileOutputStream(destFile);
            byte[] cache = new byte[CACHE_SIZE];
            int nRead = 0;
            while ((nRead = in.read(cache)) != -1) {
                out.write(cache, 0, nRead);
                out.flush();
            }
            out.close();
            in.close();
        }
    
    }
    

    展开全文
  • 对称加密概述

    万次阅读 多人点赞 2018-07-29 16:16:15
    对称加密概述 前言 在阅读《精通比特币》的过程中,我发现比特币系统中有两个重要的概念需要利用非对称加密技术: 比特币地址的生成 交易合法性的验证 因此,我用了几天时间学习了密码学基础知识,尤其是非...
  • 对称加密--(cbc)DES原理及完整源码

    千次阅读 2019-04-10 21:23:57
    所以自己用c写了一个支持大数据的cbc-des库,未来还会在库里添加其他的加密方式。 使用时候修改.h,进行裁剪,在文件里放入明文就行了。亲测可行,需要的留下邮箱 /* ======================SIMPLE_DES==============...
  • 常用的对称加密算法

    千次阅读 2019-10-26 17:20:38
    文章目录`1、DES(Data Encryption ...由于其速度快,对称加密通常在消息发送方需要加密大量数据时使用。对称加密也称为密钥加密。 所谓对称,就是采用这种加密方法的双方使用方式用同样的密钥进行加密和解密...
  • 1、场景 小天:准备剁手买买买的用户 网站A:卖东西的网址 黑客B:仿冒网站A的黑客网站;或者仿冒用户小天,获取A发来的数据 ...1)黑客网站B可能冒充网站A截获小天的请求消息 ...3、对称加密  采用对称加...
  • 第一 对称加密对称加密是指,加密方和解密方使用同样的秘钥来进行加密和解密。在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去...
  • 对称加密和非对称加密

    千次阅读 2019-06-15 20:36:31
    对称加密 什么是对称加密对称加密就是指,加密和解密使用同一个密钥的加密方式。 对称加密的工作过程 发送方使用密钥将明文数据加密成密文,然后发送出去,接收方收到密文后,使用同一个密钥将密文解密成明文...
  • 常用加密算法之非对称加密算法

    万次阅读 2018-03-16 21:44:45
    对称加密算法 非对称加密算法是一种密钥的保密方法。非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有...
  • 对称加密算法

    千次阅读 2018-11-24 10:12:55
    对称加密算法有DES、DESede、AES、Blowfish,以及RC2和RC4算法,还有其他第三方提供的软件包提供的Bouncy Castle 提供的IDEA算法 这里面DES算是最经典的算法,DESede是DES算法的变种,AES算是DES算法的替代者; DES...
  • 对称加密算法和非对称加密算法

    千次阅读 2019-03-17 15:59:04
    有一种加密算法叫做对称加密对称加密是以前比较常见的一种加密方式。所谓对称加密的意思是说假如有一个人A,他想把一个信号m传递给B,他不能直接将这个信息传递给B,否则会有人可能会窃听。于是通过一些算法,...
  • 数据传输加密  在开发应用过程中,客户端与服务端经常需要进行数据传输,涉及到重要隐私信息时...在这里我主要向大家介绍一下我在开发过程中使用到的加密算法,RSA加密算法+AES加密算法。简单地介绍一下这两种算法吧
  • 对称与非对称加密算法

    万次阅读 2018-08-30 10:31:47
    一、对称加密算法   指加密和解密使用相同密钥的加密算法。对称加密算法用来对敏感数据等信息进行加密,常用的算法包括DES、3DES、AES、DESX、Blowfish、、RC4、RC5、RC6。  DES(Data Encryption Standard):...
  • 一、对称加密算法   指加密和解密使用相同密钥的加密算法。对称加密算法用来对敏感数据等信息进行加密,常用的算法包括DES、3DES、AES、DESX、Blowfish、、RC4、RC5、RC6。  DES(Data Encryption Standard):...
  • 常见非对称加密算法

    万次阅读 2019-04-10 15:14:35
    对称加密技术只使用一个秘钥不同,非对称机密技术使用两个秘钥进行加解密,一个叫做公钥,一个叫做私钥,私钥自己来保管,公钥可以公开,使用公钥加密的数据必须使用私钥解密,反之亦然公钥和私钥是两个不同的秘钥...
  • 对称加密算法对称加密:加密和解密使用同一个密钥DES:Data Encryption Standard,56bits3DES:AES:Advanced (128, 192, 256bits)Blowfish,TwofishIDEA,RC6,CAST5特性:1.加密,解密使用同一个密钥,效率高2.将...
  • RSA非对称加密算法详解

    万次阅读 多人点赞 2016-12-11 23:10:50
    加密技术加密技术是对信息进行...3. 不可逆加密对称加密算法 加密过程: 将明文分成N个组,然后对各个组进行加密,形成各自的密文,最后把所有的分组密文进行合并,形成最终的密文。 优点: 算法公开、计算量小、加密
  • 对称加密算法和非对称加密算法的区别 1.对称加密算法加密和解密使用的密钥的是相同的,也就是只有一个密钥,而非对称加密算法有两个密钥,也就是加密和解密所使用的密钥是不同的 2.各自算法不同 3.对称加密算法加密...

空空如也

1 2 3 4 5 ... 20
收藏数 86,395
精华内容 34,558
关键字:

对称加密