精华内容
下载资源
问答
  • 对称密钥算法与非对称密钥算法

    万次阅读 2019-03-18 15:08:48
    对称加密:速度高,可...1.定义:对称加密算法即,加密和解密使用相同密钥的算法。(加密Key=解密key);对称密钥算法又分为分组密码 (Block Cipher)和流密码(Stream Cipher)。 常用算法包括DES(Data Encryption S...

    对称加密:速度高,可加密内容较大,用来加密会话过程中的消息

    公钥加密:加密速度较慢,但能提供更好的身份认证技术,用来加密对称加密的密钥

    一、.对称密钥算法

    1.定义:对称加密算法即,加密和解密使用相同密钥的算法。(加密Key=解密key);对称密钥算法又分为分组密码 (Block Cipher)流密码(Stream Cipher)。

    常用算法包括DES(Data Encryption Standard,数据加密算法) 、3DES(Triple Data Encryption Algorithm,三重数据加密算法)、 AES(Advanced Encryption Standard,高级加密标准,又称Rijndael加密法) 、PBE(Password-based encryption,基于密码验证)、RC4(来自Rivest Cipher 4的缩写)、 SM1 、SM4(国产)

    2.优点:加密速度快,便于硬件实现和大规模生产

    缺点:需要保障密钥安全;无法用来签名和抗抵赖;

    每对用户每次使用对称加密算法时,都需要使用其他人不知道的惟一钥匙,这会使得发收信双方所拥有的钥匙数量呈几何级数增长,密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。

        (1)DES(Data Encryption Standard,数据加密算法)
      
      DES是最基本的对称加密算法,也是使用频率最高的一种算法,加密密钥与解密密钥相同。DES出身比较好,出自IBM之手,后被美国军方采纳,之后便广泛流传,但是近些年使用越来越少,因为DES使用56位密钥,以现代计算能力,24小时内即可被破解。虽然如此,在某些简单应用中,我们还是可以使用DES加密算法。DES使用56位长度的密钥,有些提供商可能附加8位奇偶校验位。
      
      算法流程:
      
      发送者构建秘钥-->发送秘钥--> 接收者
      
      发送者明文-->DES算法+秘钥加密--> 密文--> 接收者
      
      接收者--> DES算法+秘钥解密--> 明文

    (2)3DES(Triple Data Encryption Algorithm,三重数据加密算法)
      
      3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次DES加密算法。由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解;3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。 
      DES被很多密码学机构质疑,因为算法是半公开的,因此违反柯克霍夫原则,所以在这个基础上,延伸了3重DES.
      
      算法流程:
      
      发送者构建秘钥-->发送秘钥--> 接收者
      
      发送者明文-->3DES算法+秘钥加密--> 密文--> 接收者
      
      接收者--> 3DES算法+秘钥解密--> 明文

    (3)AES(Advanced Encryption Standard,高级加密标准,又称Rijndael加密法)
      
      高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。 
      
      AES是目前使用最多的对称加密算法之一,AES至今尚未听说有被破解的案例。
      
      AES通常用于移动通信系统加密以及基于SSH协议的软件,如SSH Client,secureCRT
      
      AES是用来替代DES的,因为DES有很多被破解,而3DES效率又比较慢
      
      AES加密算法的默认密钥长度为128,还可以选择192、256.
      
      注意:JDK实现AES算法,使用256位密钥长度时要获得无政策限制权限文件,BC不会存在该问题。无政策限制权限是指某些国家的进口管制限制,java发布的运行环境包中中的加解密有一定限制。
      
       算法流程:
      
      发送者构建秘钥-->发送秘钥--> 接收者
      
      发送者明文-->AES算法+秘钥加密--> 密文--> 接收者
      
      接收者--> AES算法+秘钥解密--> 明文

    (4)PBE(Password-based encryption,基于密码验证)
      
      PBE算法(Password Based Encryption,基于口令加密)是一种基于口令的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数杂凑多重加密等方法保证数据的安全性。PBE算法在加密过程中并不是直接使用口令来加密,而是加密的密钥由口令生成,这个功能由PBE算法中的KDF函数完成。KDF函数的实现过程为:将用户输入的口令首先通过“盐”(salt)的扰乱产生准密钥,再将准密钥经过散列函数多次迭代后生成最终加密密钥,密钥生成后,PBE算法再选用对称加密算法对数据进行加密,可以选择DES、3DES、RC5等对称加密算法。
      
      特点:
      
      结合了消息摘要算法和对称加密算法的优点,本质上是对MD5/SHA以及DES/3DES/AES算法的包装,不是新的算法,不过也是最为牛逼的一种方式。
      
      盐:指加密的随机字符串或者口令等,也可以人为是一些扰码,防止密码的暴力破解
      
      算法流程:
      
      发送者构建口令-->发送口令--> 接收者
      
      发送者构建盐
      
      发送者明文-->PBE算法+口令+盐加密--> 密文(同时发送盐)--> 接收者
      
      接收者--> PBE算法+口令+盐解密--> 明文
     (5)RC4(来自Rivest Cipher 4的缩写) 

           RC4于1987年提出,和DES算法一样。是一种对称加密算法,也就是说使用的密钥为单钥(或称为私钥)。

    但不同于DES的是。RC4不是对明文进行分组处理,而是字节流的方式依次加密明文中的每个字节。解密的时候也是依次对密文中的每个字节进行解密。

           特点:

            算法简单,执行速度快;

           并且密钥长度是可变的,可变范围为1-256字节(8-2048比特)。

         (在现在技术支持的前提下,当密钥长度为128比特时,用暴力法搜索密钥已经不太可行,所以能够预见RC4的密钥范围任然能够在今后相当长的时间里抵御暴力搜索密钥的攻击。实际上,现在也没有找到对于128bit密钥长度的RC4加密算法的有效攻击方法。)

          关键变量:

           1、密钥流:RC4算法的关键是依据明文和密钥生成相应的密钥流,密钥流的长度和明文的长度是相应的。也就是说明文的长度是500字节,那么密钥流也是500字节。当然,加密生成的密文也是500字节。由于密文第i字节=明文第i字节^密钥流第i字节;

           2、状态向量S:长度为256。S[0],S[1].....S[255]。每一个单元都是一个字节。算法执行的不论什么时候。S都包含0-255的8比特数的排列组合,仅仅只是值的位置发生了变换;

           3、暂时向量T:长度也为256,每一个单元也是一个字节。

    假设密钥的长度是256字节。就直接把密钥的值赋给T,否则,轮转地将密钥的每一个字节赋给T。

           4、密钥K:长度为1-256字节。注意密钥的长度keylen与明文长度、密钥流的长度没有必定关系。通常密钥的长度趣味16字节(128比特)。

    (6)SM1

    定义:国密 SM1( SM1 cryptographic algorithm),国密 SM1 算法是由国家密码管理局编制的一种商用密码分组标准对称算法

        SM1 为对称加密。其加密强度与AES相当。该算法不公开,调用该算法时,需要通过加密芯片的接口进行调用;该算法是国家密码管理部门审批的 SM1 分组密码算法 , 分组长度和密钥长度都为 128 比特, 仅以 IP 核的形式存在于芯片中。采用该算法已经研制了系列芯片、智能 IC 卡、智能密码钥匙、加密卡、加 密机等安全产品,广泛应用于电子政务、电子商务及国民经济的各个应用领域(包括国家政 务

    通、警务通等重要领域)。

    (7)SM4

    2012年3月,国家密码管理局正式公布了包含SM4分组密码算法在内的《祖冲之序列密码算法》等6项密码行业标准。其分组长度为128bit,密钥长度也为128bit。加密算法与密钥扩展算法均采用32轮非线性迭代结构,以字(32位)为单位进行加密运算,每一次迭代运算均为一轮变换函数F。SM4算法加/解密算法的结构相同,只是使用轮密钥相反,其中解密轮密钥是加密轮密钥的逆序。

    3.分组密码 (Block Cipher)

    一次加密解密操作作用于一个数据块,例如64位算法:DES、 3DES、AES 、DES替代者、RC2、 RC5、BLOWFISH 、TWOFISH

    分组密码设计原则:

    安全性角度:

    (1)“混乱原则”:为了避免密码分析者利用明文与密文之间的依赖关系进行破译,密码的设计应该保证这种依赖关系足够复杂。

    (2)“扩散原则” :为避免密码分析者对密钥逐段破译,密码的设计应该保证密钥的每位数字能够影响密文中的多位数字 ;同时,为了避免密码分析者利用明文的统计特性,密码的设计应该保证明文的每位数字能够影响密文中的多位数字,从而隐藏明文的统计特性。

    可实现性角度:

    (1)应该具有标准的组件结构 (子模块),以适应超大规模集成电路的实现。

    (2)分组密码的运算能在子模块上通过简单的运算进行

    4.流密码(Stream Cipher)

    一次加密解密操作作用于一位或一个字节。如算法:RC4

    5.对称密码模式:

    电子密码本(Eletronic CoodBook, ECB),密码分组链(Cipher Block Chaining , CBC),密文反馈( Cipher FeedBack , CFB),输出反馈(Output FeedBack , OFB )。

    电子密码本模式 Electronic Code Book:

    优点:

    (1)简单;(2)有利于并行计算;(3)误差不会被传送;

    缺点:

    (1)不能隐藏明文的模式;(2)可能对明文进行主动攻击;

    密码分组链模式 Cipher Block Chaining:

    优点:不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的 标准。

    缺点:(1)不利于并行计算;(2)误差传递;(3)需要初始化向量IV

    二.非对称密钥算法(也称公开密钥算法)

    1.定义:非对称密码体制也叫公开密钥密码体制、双密钥密码体制。其原理是加密密钥与解密密钥不同,形成一个密钥对,用其中一个密钥加密的结果,可以用另一个密钥来解密 。

          目前普遍使用的非对称加密算法主要有RSA、Elgamal(离散对数)、ECC(椭圆曲线)等

    2.特点:加密和解密使用不同的密钥;一个密钥公开,称公钥;一个密钥保密,称私钥

    常用算法:RSA 、ECC、 DSA(Digital Signature Algorithm)

    优点:密钥分配,不必保持信道的保密性 ;可以用来签名和防抵赖

    (1)RSA加密签名特性:

    RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。

    在RSA加密算法,由于PADDING的不一致,会导致加密结果每次不一致;使用PKCS1Padding加密结果不一致;使用NoPadding加密结果一致;签名结果每次是一致的。

    RSA算法的安全性:

    在理论上,rsa 的安全性取决于模n分解的困难性,但数学上至今还未证明分解模就是攻击rsa的最佳办法。

    人们完全可以设想有另外的途径破译rsa,如求解密指数d或找到(p-1)(q-1)等。但这些途径都不比分解n来的容易。

    已公开的或已知的攻击方法:

    1,针对RSA最流行的攻击一般是基于大数因数分解。

    1999年,RSA-155 (512 bits)被成功分解,花了五个月时间(约8000 MIPS年)和224 CPU hours在一台有3.2G中央内存的Cray C916计算机上完成。

    ECC 160bit算法等级,相当于RSA 1024bit密钥提供的保密强度,210bit与RSA2048算法强度相当,计算量则更小,处理速度更快,存储空间和传输带宽占用较少

    2,秀尔算法

    量子计算里的秀尔算法能使穷举的效率大大的提高。由于RSA算法是基于大数分解(无法抵抗穷举攻击),因此在未来量子计算能对RSA算法构成较大的威胁。一个拥有N量子比特的量子计算机,每次可进行2^N次运算,理论上讲,密钥为1024位长的RSA算法,用一台512量子比特位的量子计算机在1秒内即可破解。

    (2)非对称密钥算法-ECC:(ECC-椭圆曲线加密 Ellipse Curve Cryptography)

    基于椭圆曲线理论的公钥加密技术(1985)与传统的基于大质数因子分解困难性的加密方法不同,ECC通过椭圆曲线方程式的性质产生密钥

    (3)DSA(Digital Signature Algorithm):数字签名算法,是一种标准的 DSS(数字签名标准),严格来说不算加密算法;

    ECDSA签名算法:

    (1)选择一条椭圆曲线Ep(a,b),和基点G;

    (2)选择私有密钥k(k<n,n为G的阶),利用基点G计算公开密钥K=kG;

    (3)产生一个随机整数r(r<n),计算点R=rG;

    (4)将原数据和点R的坐标值x,y作为参数,计算SHA1做为hash,即Hash=SHA1(原数据,x,y);

    (5)计算s≡r - Hash * k (mod n)

    (6)r和s做为签名值,如果r和s其中一个为0,重新从第3步开始执行

    ECDSA验证:

    (1)接受方在收到消息(m)和签名值(r,s)后,进行以下运算

    (2)计算:sG+H(m)P=(x1,y1), r1≡ x1 mod p。

    (3)验证等式:r1 ≡ r mod p。

    (4)如果等式成立,接受签名,否则签名无效。

    各取所长:对称密码和非对称密码结合;使用对称密码加密数据;协商对称密钥算法;非对称密码加密密钥;公钥加密密钥;私钥解密;数字证书解决了数据完整性和不可否认性

    3.HASH算法:

    特点:输入长度不定,输出长度为定值;不可逆;碰撞几率大

    常见算法:

    MD5     128Bit

    Sha-1   160Bit

    SHA-224, SHA-256, SHA-384 和SHA-512

    HASH算法主要应用于:散列算法最重要的用途在于给证书、文档、密码等高安全系数的内容添加加密保护。这一方面的用途主要是得益于散列算法的不可逆性,这种不可逆性体现在,你不仅不可能根据一段通过散列算法得到的指纹来获得原有的文件,也不可能简单地创造一个文件并让它的指纹与一段目标指纹相一致。

    在密码学中,hash算法的作用主要是用于消息摘要和签名

    一个优秀的 hash 算法,将能实现:

    (1)正向快速:给定明文和 hash 算法,在有限时间和有限资源内能计算出 hash 值。

    (2)逆向困难:给定(若干) hash 值,在有限时间内很难(基本不可能)逆推出明文。

    (3)输入敏感:原始输入信息修改一点信息,产生的 hash 值看起来应该都有很大不同。

    (4)冲突避免:很难找到两段内容不同的明文,使得它们的 hash 值一致(发生冲突)。即对于任意两个不同的数据块,其hash值相同的可能性极小;对于一个给定的数据块,找到和它hash值相同的数据块极为困难。

    (ECDSA每次签名信息是否一样:不一样,因为ECDSA签名算法的第(3)步产生一个随机整数r(r<n),计算点R=rG;导致最终的签名信息不一样。)

    Sha-1   160Bit

        安全哈希加密技术,是当今世界最先近的加密算法。主要用于文件身份识别、数字签名和口令加密等。
        对于明文信息A,通过SHA1算法,生成一条160位长的识别码B。且明文信息A和识别码B之间同时满足以下条件:
         1、对于任意两条不同的明文信息A1、A2,其识别码B1、B2都不相同。
         2、无法通过逆向算法由识别码B倒推出明文信息A。
    MOONCRM的用户密码采用SHA1加密存储,即服务器上存储的只是由用户密码生成的识别码,而用户密码本身并没有存储在服务器上。用户输入登陆口令时,系统会根据输入口令生成相应识别码并与系统中所存储的识别码进行比较,如二者一致,则认为口令正确。系统中没有存储用户原始的口令值,即使有人获得口令文件,也无法破解用户登陆密码,确保用户密码绝对安全。

    MD5     128Bit

      Message-Digest泛指字节串(Message)的Hash变换,就是把一个任意长度的字节串变换成一定长的大整数。请注意是“字节串”而不是“字符串”这个词,是因为这种变换只与字节的值有关,与字符集或编码方式无关。
      MD5将任意长度的“字节串”变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数
       MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被“篡改”。举个例子,你将一段话写在一个叫 readme.txt文件中,并对这个readme.txt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现(两个MD5值不相同)。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。 

           MD5是一种不可逆的加密算法 安全性很高 一般在网上用作判断文件完整性
    如果一个文件被修改或不完整 算出来的MD5码是和原来不一样的 所以当你害怕下的东西有病毒或木马或不完整 可以用MD5计算器算一下 再和网站上提供的值对比关于软件很多地方有下的 软件就一个作用 把软件拖进去 然后算出MD5码
    这个基本上是软件内部利用MD5加密导致,本身几乎无效验方法,因为MD5不可以反编译,方法写个过程,或下载MD5文件 调用MD5(PASSWORD)
    MD5中的MD代表Message Digest,就是信息摘要的意思,不过这个信息摘要不是信息内容的缩写,而是根据公开的MD5算法对原信息进行数学变换后得到的一个128位(bit)的特征码。
           这个特征码有如下特性,首先它不可逆,例如我有一段秘密的文字如:"My Secret Words",经算法变换后得到MD5码(b9944e9367d2e40dd1f0c4040d4daaf7),把这个码告诉其他人,他们根据这个MD5码是没有系统的方法可以知道你原来的文字是什么的。其次,这个码具有高度的离散性,也就是说,原信息的一点点变化就会导致MD5的巨大变化,例如"ABC" MD5(902fbdd2b1df0c4f70b4a5d23525e932)和"ABC "(多了一空格)MD5(12c774468f981a9487c30773d8093561)差别非常大,而且之间没有任何关系,也就是说产生的MD5码是不可预测的。最后由于这个码有128位那么长,所以任意信息之间具有相同MD5码的可能性非常之低,通常被认为是不可能的。 所以一般认为MD5码可以唯一地代表原信息的特征,通常用于密码的加密存储,数字签名,文件完整性验证等。2004年,已经被山东大学王小云教授破解了。比如:2345 两个相加的和再相乘 2+3=5 4+5=9 5*9=45

     

    展开全文
  • 1. 对称算法 加解密使用一个密钥 有四种加密模式:电子密码本模式(ECB)、加密块链模式(CBC)、加密反馈模式(CFB)、输出反馈模式(OFB) 2. 摘要算法 消息摘要算法是不可逆。 常用的“消息摘要”算法有: MD2、MD...

    1.  对称算法

    加解密使用一个密钥

    有四种加密模式:电子密码本模式(ECB)、加密块链模式(CBC)、加密反馈模式(CFB)、输出反馈模式(OFB)

    2. 摘要算法

    消息摘要算法是不可逆

    常用的“消息摘要”算法有: MD2、MD4、MD5、SHA、SHA-1/256/383/512等。

           常用的摘要算法主要有MD5和SHA1。MD5的输出结果为16字节,sha1的输出结果为20字节。

    3. 公钥算法

    加解密使用不同的密钥。公钥加密,私钥解密。

    常用的算法有:RSA、DSA、DH和ECC


    a. RSA 它的安全性是基于大整数素因子分解的困难性。

    大多数使用公钥密码进行加密和数字签名的产品和标准使用的都是RSA算法。


    算法:

    1. 选择2个质数p、q;

    2. n = p * q ;

    3. 欧拉函数Φ(n) = (p - 1)(q - 1)

    4. 选择整数e,使e与Φ(n)互质,且1 < e < Φ(n)

    5. 计算d,使d * e = 1 mod Φ(n)

    其中,公钥KU={e, n}, 私钥 KR = { d, n }。

    b.  DSA 只用做数字签名 安全性基于解离散对数的困难性

    DSA签名算法中用到了以下参数: 

    p是L位长的素数,其中L从512到1024且是64的倍数。 

    q是160位长且与p-1互素的因子 ,其中h是小于p-1并且满足 大于1的任意数。 

    x是小于q的数。 


    算法使用一个单向散列函数H(m)。

    标准指定了安全散列算法(SHA)。三个参数p,q和g是公开的,且可以被网络中所有的用户公有。

    私人密钥是x,公开密钥是y。 


    对消息m签名时: 

    (1) 发送者产生一个小于q的随机数k。 

    (2) 发送者产生: r和s就是发送者的签名,发送者将它们发送给接受者。 

    (3) 接受者通过计算来验证签名:

    如果v=r,则签名有效。


    c.  Diffie-Hellman密钥交换

    实质是一个通信双方进行的密钥协定,安全性基于有限域上计算离散对数的困难性。

    d. 椭圆曲线密码机制( ECC )

    椭圆曲线的数量乘是这样定义的:设E为域K上的椭圆曲线,G为E上的一点,

    这个点被一个正整数k相乘的乘法定义为 k个G相加,因而有

    kG = G + G + … + G       (共有k个G)

    若存在椭圆曲线上的另一点N ≠ G,满足方程kG = N。

    容易看出,给定k和G,计算N相对容易。而给定N和G,计算k = logG N相对困难。这就是椭圆曲线离散对数问题。


    4. 回调函数

    展开全文
  • SM4国密对称算法源码解析

    万次阅读 多人点赞 2018-10-11 15:22:49
    其中SM2为非对称加密算法,SM3为哈希摘要算法,SM4为对称加密算法。 1.在SM4算法源文件中主要有以下几个函数: void sm4_setkey_enc( sm4_context *ctx, unsigned char key[16] ); void sm4_setkey_dec( sm4_...

    最近在研究国密算法,主要分为:SM2、SM3、SM4。其中SM2为非对称加密算法,SM3为哈希摘要算法,SM4为对称加密算法。

    1.在SM4算法源文件中主要有以下几个函数:

    void sm4_setkey_enc( sm4_context *ctx, unsigned char key[16] );
    void sm4_setkey_dec( sm4_context *ctx, unsigned char key[16] );
    void sm4_crypt_ecb( sm4_context *ctx, int mode,int length, unsigned char *input,
                        unsigned char *output);
    void sm4_crypt_cbc( sm4_context *ctx, int mode, int length,
                         unsigned char iv[16], unsigned char *input,
                         unsigned char *output );

    2.还有一个重要的结构体:

    /**
     * \brief          SM4 context structure
     */
    typedef struct
    {
        int mode;                   /*!<  encrypt/decrypt   */
        unsigned long sk[32];       /*!<  SM4 subkeys       */
    }
    sm4_context;

    结构体中的mode参数控制加密还是解密,其中mode=1为加密,mode=0为解密。数组sk为轮密钥。SM4为32轮加密变换。

    3.加密函数:

     /**
     * \brief          SM4 key schedule (128-bit, encryption)
     *
     * \param ctx      SM4 context to be initialized
     * \param key      16-byte secret key
     */
    void sm4_setkey_enc(sm4_context *ctx,unsigned char key[16]);

    这个函数是用来加密明文的,一个参数分别为sm4_context *ctx和一个key。

    其内部会调用static void sm4_setkey( unsigned long SK[32], unsigned char key[16] )函数

    这个函数是用来设置密钥的,这个函数内部会对当前传入的主密钥进行32轮的迭代,每次迭代的轮密钥都被存放到ctx结构中的sk数组中。

    4.解密函数:

    /**
     * \brief          SM4 key schedule (128-bit, decryption)
     *
     * \param ctx      SM4 context to be initialized
     * \param key      16-byte secret key
     */
    void sm4_setkey_dec( sm4_context *ctx, unsigned char key[16] );
    

    这个函数为解密函数,是进行密文解密的。参数与加密函数一样。

    5.ECB工作模式:

    /**
     * \brief          SM4-ECB block encryption/decryption
     * \param ctx      SM4 context
     * \param mode     SM4_ENCRYPT or SM4_DECRYPT
     * \param length   length of the input data
     * \param input    input block
     * \param output   output block
     */
    void sm4_crypt_ecb( sm4_context *ctx, int mode, int length,
                         unsigned char *input,
                         unsigned char *output);

    这个函数的作用是使用ECB模式(ECB(Electronic Codebook,电码本),ECB模式是分组密码的一种最基本的工作模式。根据length的长度来进行循环,每次循环都调用sm4_one_round进行加密或者解密,到底是加密还是解密,主要是根据第二个参数Mode来进行决定。

    6. CBC工作模式:

    /**
     * \brief          SM4-CBC buffer encryption/decryption
     * \param ctx      SM4 context
     * \param mode     SM4_ENCRYPT or SM4_DECRYPT
     * \param length   length of the input data
     * \param iv       initialization vector (updated after use)
     * \param input    buffer holding the input data
     * \param output   buffer holding the output data
     */
    void sm4_crypt_cbc( sm4_context *ctx, int mode, int length,
                         unsigned char iv[16],
                         unsigned char *input,
                         unsigned char *output );

    以上就是SM4加密算法的函数简介,具体的代码实现可不用掌握,下面是完整代码:

    7.sm4.h头文件

    /**
     * \file sm4.h
     */
    #ifndef XYSSL_SM4_H
    #define XYSSL_SM4_H
    
    #define SM4_ENCRYPT     1
    #define SM4_DECRYPT     0
    
    /**
     * \brief          SM4 context structure
     */
    typedef struct
    {
        int mode;                   /*!<  encrypt/decrypt   */
        unsigned long sk[32];       /*!<  SM4 subkeys       */
    }
    sm4_context;
    
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    /**
     * \brief          SM4 key schedule (128-bit, encryption)
     *
     * \param ctx      SM4 context to be initialized
     * \param key      16-byte secret key
     */
    void sm4_setkey_enc( sm4_context *ctx, unsigned char key[16] );
    
    /**
     * \brief          SM4 key schedule (128-bit, decryption)
     *
     * \param ctx      SM4 context to be initialized
     * \param key      16-byte secret key
     */
    void sm4_setkey_dec( sm4_context *ctx, unsigned char key[16] );
    
    /**
     * \brief          SM4-ECB block encryption/decryption
     * \param ctx      SM4 context
     * \param mode     SM4_ENCRYPT or SM4_DECRYPT
     * \param length   length of the input data
     * \param input    input block
     * \param output   output block
     */
    void sm4_crypt_ecb( sm4_context *ctx,
    				     int mode,
    					 int length,
                         unsigned char *input,
                         unsigned char *output);
    
    /**
     * \brief          SM4-CBC buffer encryption/decryption
     * \param ctx      SM4 context
     * \param mode     SM4_ENCRYPT or SM4_DECRYPT
     * \param length   length of the input data
     * \param iv       initialization vector (updated after use)
     * \param input    buffer holding the input data
     * \param output   buffer holding the output data
     */
    void sm4_crypt_cbc( sm4_context *ctx,
                         int mode,
                         int length,
                         unsigned char iv[16],
                         unsigned char *input,
                         unsigned char *output );
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif /* sm4.h */
    

    8.sm4.c源文件

    /*
     * SM4 Encryption alogrithm (SMS4 algorithm)
     * GM/T 0002-2012 Chinese National Standard ref:http://www.oscca.gov.cn/ 
     * thanks to Xyssl
     * thnaks and refers to http://hi.baidu.com/numax/blog/item/80addfefddfb93e4cf1b3e61.html
     * author:goldboar
     * email:goldboar@163.com
     * 2012-4-20
     */
    
    // Test vector 1
    // plain: 01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
    // key:   01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
    // 	   round key and temp computing result:
    // 	   rk[ 0] = f12186f9 X[ 0] = 27fad345
    // 		   rk[ 1] = 41662b61 X[ 1] = a18b4cb2
    // 		   rk[ 2] = 5a6ab19a X[ 2] = 11c1e22a
    // 		   rk[ 3] = 7ba92077 X[ 3] = cc13e2ee
    // 		   rk[ 4] = 367360f4 X[ 4] = f87c5bd5
    // 		   rk[ 5] = 776a0c61 X[ 5] = 33220757
    // 		   rk[ 6] = b6bb89b3 X[ 6] = 77f4c297
    // 		   rk[ 7] = 24763151 X[ 7] = 7a96f2eb
    // 		   rk[ 8] = a520307c X[ 8] = 27dac07f
    // 		   rk[ 9] = b7584dbd X[ 9] = 42dd0f19
    // 		   rk[10] = c30753ed X[10] = b8a5da02
    // 		   rk[11] = 7ee55b57 X[11] = 907127fa
    // 		   rk[12] = 6988608c X[12] = 8b952b83
    // 		   rk[13] = 30d895b7 X[13] = d42b7c59
    // 		   rk[14] = 44ba14af X[14] = 2ffc5831
    // 		   rk[15] = 104495a1 X[15] = f69e6888
    // 		   rk[16] = d120b428 X[16] = af2432c4
    // 		   rk[17] = 73b55fa3 X[17] = ed1ec85e
    // 		   rk[18] = cc874966 X[18] = 55a3ba22
    // 		   rk[19] = 92244439 X[19] = 124b18aa
    // 		   rk[20] = e89e641f X[20] = 6ae7725f
    // 		   rk[21] = 98ca015a X[21] = f4cba1f9
    // 		   rk[22] = c7159060 X[22] = 1dcdfa10
    // 		   rk[23] = 99e1fd2e X[23] = 2ff60603
    // 		   rk[24] = b79bd80c X[24] = eff24fdc
    // 		   rk[25] = 1d2115b0 X[25] = 6fe46b75
    // 		   rk[26] = 0e228aeb X[26] = 893450ad
    // 		   rk[27] = f1780c81 X[27] = 7b938f4c
    // 		   rk[28] = 428d3654 X[28] = 536e4246
    // 		   rk[29] = 62293496 X[29] = 86b3e94f
    // 		   rk[30] = 01cf72e5 X[30] = d206965e
    // 		   rk[31] = 9124a012 X[31] = 681edf34
    // cypher: 68 1e df 34 d2 06 96 5e 86 b3 e9 4f 53 6e 42 46
    // 		
    // test vector 2
    // the same key and plain 1000000 times coumpting 
    // plain:  01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
    // key:    01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
    // cypher: 59 52 98 c7 c6 fd 27 1f 04 02 f8 04 c3 3d 3f 66
    
    #include "sm4.h"
    #include <string.h>
    #include <stdio.h>
    
    /*
     * 32-bit integer manipulation macros (big endian)
     */
    #ifndef GET_ULONG_BE
    #define GET_ULONG_BE(n,b,i)                             \
    {                                                       \
        (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
            | ( (unsigned long) (b)[(i) + 1] << 16 )        \
            | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
            | ( (unsigned long) (b)[(i) + 3]       );       \
    }
    #endif
    
    #ifndef PUT_ULONG_BE
    #define PUT_ULONG_BE(n,b,i)                             \
    {                                                       \
        (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
        (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
        (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
        (b)[(i) + 3] = (unsigned char) ( (n)       );       \
    }
    #endif
    
    /*
     *rotate shift left marco definition
     *
     */
    #define  SHL(x,n) (((x) & 0xFFFFFFFF) << n)
    #define ROTL(x,n) (SHL((x),n) | ((x) >> (32 - n)))
    
    #define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; }
    
    /*
     * Expanded SM4 S-boxes
     /* Sbox table: 8bits input convert to 8 bits output*/
     
    static const unsigned char SboxTable[16][16] = 
    {
    {0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05},
    {0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99},
    {0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62},
    {0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6},
    {0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8},
    {0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35},
    {0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87},
    {0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e},
    {0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1},
    {0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3},
    {0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f},
    {0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51},
    {0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8},
    {0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0},
    {0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84},
    {0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48}
    };
    
    /* System parameter */
    static const unsigned long FK[4] = {0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc};
    
    /* fixed parameter */
    static const unsigned long CK[32] =
    {
    0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
    0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
    0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
    0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
    0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
    0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
    0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
    0x10171e25,0x2c333a41,0x484f565d,0x646b7279
    };
    
    
    /*
     * private function:
     * look up in SboxTable and get the related value.
     * args:    [in] inch: 0x00~0xFF (8 bits unsigned value).
     */
    static unsigned char sm4Sbox(unsigned char inch)
    {
        unsigned char *pTable = (unsigned char *)SboxTable;
        unsigned char retVal = (unsigned char)(pTable[inch]);
        return retVal;
    }
    
    /*
     * private F(Lt) function:
     * "T algorithm" == "L algorithm" + "t algorithm".
     * args:    [in] a: a is a 32 bits unsigned value;
     * return: c: c is calculated with line algorithm "L" and nonline algorithm "t"
     */
    static unsigned long sm4Lt(unsigned long ka)
    {
        unsigned long bb = 0;
        unsigned long c = 0;
        unsigned char a[4];
    	unsigned char b[4];
        PUT_ULONG_BE(ka,a,0)
        b[0] = sm4Sbox(a[0]);
        b[1] = sm4Sbox(a[1]);
        b[2] = sm4Sbox(a[2]);
        b[3] = sm4Sbox(a[3]);
    	GET_ULONG_BE(bb,b,0)
        c =bb^(ROTL(bb, 2))^(ROTL(bb, 10))^(ROTL(bb, 18))^(ROTL(bb, 24));
        return c;
    }
    
    /*
     * private F function:
     * Calculating and getting encryption/decryption contents.
     * args:    [in] x0: original contents;
     * args:    [in] x1: original contents;
     * args:    [in] x2: original contents;
     * args:    [in] x3: original contents;
     * args:    [in] rk: encryption/decryption key;
     * return the contents of encryption/decryption contents.
     */
    static unsigned long sm4F(unsigned long x0, unsigned long x1, unsigned long x2, unsigned long x3, unsigned long rk)
    {
        return (x0^sm4Lt(x1^x2^x3^rk));
    }
    
    
    /* private function:
     * Calculating round encryption key.
     * args:    [in] a: a is a 32 bits unsigned value;
     * return: sk[i]: i{0,1,2,3,...31}.
     */
    static unsigned long sm4CalciRK(unsigned long ka)
    {
        unsigned long bb = 0;
        unsigned long rk = 0;
        unsigned char a[4];
        unsigned char b[4];
        PUT_ULONG_BE(ka,a,0)
        b[0] = sm4Sbox(a[0]);
        b[1] = sm4Sbox(a[1]);
        b[2] = sm4Sbox(a[2]);
        b[3] = sm4Sbox(a[3]);
    	GET_ULONG_BE(bb,b,0)
        rk = bb^(ROTL(bb, 13))^(ROTL(bb, 23));
        return rk;
    }
    
    static void sm4_setkey( unsigned long SK[32], unsigned char key[16] )
    {
        unsigned long MK[4];
        unsigned long k[36];
        unsigned long i = 0;
    
        GET_ULONG_BE( MK[0], key, 0 );
        GET_ULONG_BE( MK[1], key, 4 );
        GET_ULONG_BE( MK[2], key, 8 );
        GET_ULONG_BE( MK[3], key, 12 );
        k[0] = MK[0]^FK[0];
        k[1] = MK[1]^FK[1];
        k[2] = MK[2]^FK[2];
        k[3] = MK[3]^FK[3];
        for(; i<32; i++)
        {
            k[i+4] = k[i] ^ (sm4CalciRK(k[i+1]^k[i+2]^k[i+3]^CK[i]));
            SK[i] = k[i+4];
    	}
    
    }
    
    /*
     * SM4 standard one round processing
     *
     */
    static void sm4_one_round( unsigned long sk[32],
                        unsigned char input[16],
                        unsigned char output[16] )
    {
        unsigned long i = 0;
        unsigned long ulbuf[36];
    
        memset(ulbuf, 0, sizeof(ulbuf));
        GET_ULONG_BE( ulbuf[0], input, 0 )
        GET_ULONG_BE( ulbuf[1], input, 4 )
        GET_ULONG_BE( ulbuf[2], input, 8 )
        GET_ULONG_BE( ulbuf[3], input, 12 )
        while(i<32)
        {
            ulbuf[i+4] = sm4F(ulbuf[i], ulbuf[i+1], ulbuf[i+2], ulbuf[i+3], sk[i]);
    // #ifdef _DEBUG
    //        	printf("rk(%02d) = 0x%08x,  X(%02d) = 0x%08x \n",i,sk[i], i, ulbuf[i+4] );
    // #endif
    	    i++;
        }
    	PUT_ULONG_BE(ulbuf[35],output,0);
    	PUT_ULONG_BE(ulbuf[34],output,4);
    	PUT_ULONG_BE(ulbuf[33],output,8);
    	PUT_ULONG_BE(ulbuf[32],output,12);
    }
    
    /*
     * SM4 key schedule (128-bit, encryption)
     */
    void sm4_setkey_enc( sm4_context *ctx, unsigned char key[16] )
    {
        ctx->mode = SM4_ENCRYPT;
    	sm4_setkey( ctx->sk, key );
    }
    
    /*
     * SM4 key schedule (128-bit, decryption)
     */
    void sm4_setkey_dec( sm4_context *ctx, unsigned char key[16] )
    {
        int i;
    	ctx->mode = SM4_ENCRYPT;
        sm4_setkey( ctx->sk, key );
        for( i = 0; i < 16; i ++ )
        {
            SWAP( ctx->sk[ i ], ctx->sk[ 31-i] );
        }
    }
    
    
    /*
     * SM4-ECB block encryption/decryption
     */
    
    void sm4_crypt_ecb( sm4_context *ctx,
    				   int mode,
    				   int length,
    				   unsigned char *input,
                       unsigned char *output)
    {
        while( length > 0 )
        {
            sm4_one_round( ctx->sk, input, output );
            input  += 16;
            output += 16;
            length -= 16;
        }
    
    }
    
    /*
     * SM4-CBC buffer encryption/decryption
     */
    void sm4_crypt_cbc( sm4_context *ctx,
                        int mode,
                        int length,
                        unsigned char iv[16],
                        unsigned char *input,
                        unsigned char *output )
    {
        int i;
        unsigned char temp[16];
    
        if( mode == SM4_ENCRYPT )
        {
            while( length > 0 )
            {
                for( i = 0; i < 16; i++ )
                    output[i] = (unsigned char)( input[i] ^ iv[i] );
    
                sm4_one_round( ctx->sk, output, output );
                memcpy( iv, output, 16 );
    
                input  += 16;
                output += 16;
                length -= 16;
            }
        }
        else /* SM4_DECRYPT */
        {
            while( length > 0 )
            {
                memcpy( temp, input, 16 );
                sm4_one_round( ctx->sk, input, output );
    
                for( i = 0; i < 16; i++ )
                    output[i] = (unsigned char)( output[i] ^ iv[i] );
    
                memcpy( iv, temp, 16 );
    
                input  += 16;
                output += 16;
                length -= 16;
            }
        }
    }
    

    9.测试文件

    /*
     * SM4/SMS4 algorithm test programme
     * 2012-4-21
     */
    
    #include <string.h>
    #include <stdio.h>
    #include "sm4.h"
    
    int main()
    {
    	unsigned char key[16] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
    	unsigned char input[16] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
    	unsigned char output[16];
    	sm4_context ctx;
    	unsigned long i;
    
    	//encrypt standard testing vector
    	sm4_setkey_enc(&ctx,key);
    	sm4_crypt_ecb(&ctx,1,16,input,output);
    	for(i=0;i<16;i++)
    		printf("%02x ", output[i]);
    	printf("\n");
    
    	//decrypt testing
    	sm4_setkey_dec(&ctx,key);
    	sm4_crypt_ecb(&ctx,0,16,output,output);
    	for(i=0;i<16;i++)
    		printf("%02x ", output[i]);
    	printf("\n");
    
    	//decrypt 1M times testing vector based on standards.
    	i = 0;
    	sm4_setkey_enc(&ctx,key);
    	while (i<1000000) 
        {
    		sm4_crypt_ecb(&ctx,1,16,input,input);
    		i++;
        }
    	for(i=0;i<16;i++)
    		printf("%02x ", input[i]);
    	printf("\n");
    	
        return 0;
    }
    

     

    展开全文
  • 数据传输加密  在开发应用过程中,客户端与服务端经常需要进行数据传输,涉及到重要隐私信息时...在这里我主要向大家介绍一下我在开发过程中使用到的加密算法,RSA加密算法+AES加密算法。简单地介绍一下这两种算法

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布

    转载请注明出处:http://blog.csdn.net/chay_chan/article/details/58605605

    数据传输加密

      在开发应用过程中,客户端与服务端经常需要进行数据传输,涉及到重要隐私信息时,开发者自然会想到对其进行加密,即使传输过程中被“有心人”截取,也不会将信息泄露。对于加密算法,相信不少开发者也有所耳闻,比如MD5加密,Base64加密,DES加密,AES加密,RSA加密等等。在这里我主要向大家介绍一下我在开发过程中使用到的加密算法,RSA加密算法+AES加密算法。简单地介绍一下这两种算法吧。

    RSA

      之所以叫RSA算法,是因为算法的三位发明者RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准,主要的算法原理就不多加介绍,如果对此感兴趣的话,建议去百度一下RSA算法。需要了解的是RSA算法属于非对称加密算法,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。简单的说是“公钥加密,私钥解密;私钥加密,公钥解密”。

    AES

      高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。

    为什么要结合使用这两种算法

      如果不清楚非对称算法和对称算法,也许你会问,为什么要结合使用这两种算法,单纯使用一种算法不行吗?这就要结合不同的场景和需求了。

    客户端传输重要信息给服务端,服务端返回的信息不需加密的情况

      客户端传输重要信息给服务端,服务端返回的信息不需加密,例如绑定银行卡的时候,需要传递用户的银行卡号,手机号等重要信息,客户端这边就需要对这些重要信息进行加密,使用RSA公钥加密,服务端使用RSA解密,然后返回一些普通信息,比如状态码code,提示信息msg,提示操作是成功还是失败。这种场景下,仅仅使用RSA加密是可以的。

    客户端传输重要信息给服务端,服务端返回的信息需加密的情况

      客户端传输重要信息给服务端,服务端返回的信息需加密,例如客户端登录的时候,传递用户名和密码等资料,需要进行加密,服务端验证登录信息后,返回令牌token需要进行加密,客户端解密后保存。此时就需要结合这两种算法了。至于整个流程是怎样的,在下面会慢慢通过例子向你介绍,因为如果一开始就这么多文字类的操作,可能会让读者感到一头雾水。

    使用RSA加密和解密

    产生公钥和私钥

      产生RSA公钥和密钥的方法有很多,在这里我直接使用我封装好的方法产生,都最后我会将两个算法的工具类赠送给大家。

    /**
     * 生成公钥和私钥
     * 
     * @throws Exception
     * 
     */
    public static void getKeys() throws Exception {
    	KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
    	keyPairGen.initialize(1024);
    	KeyPair keyPair = keyPairGen.generateKeyPair();
    	RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    	RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    
    	String publicKeyStr = getPublicKeyStr(publicKey);
    	String privateKeyStr = getPrivateKeyStr(privateKey);
    
    	System.out.println("公钥\r\n" + publicKeyStr);
    	System.out.println("私钥\r\n" + privateKeyStr);
    }
    
    public static String getPrivateKeyStr(PrivateKey privateKey)
    		throws Exception {
    	return new String(Base64Utils.encode(privateKey.getEncoded()));
    }
    
    public static String getPublicKeyStr(PublicKey publicKey) throws Exception {
    	return new String(Base64Utils.encode(publicKey.getEncoded()));
    }
    

    公钥

    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCRQZ5O/AOAjeYAaSFf6Rjhqovws78I716I9oGF7WxCIPmcaUa1YuyLOncCCuPsaw69+RMWjdbOBp8hd4PPM/d4mKTOVEYUE0SfxhhDTZaM5CzQEUXUyXy7icQTGR5wBjrbjU1yHCKOf5PJJZZQWB06husSFZ40TdL7FdlBpZ1u1QIDAQAB
    

    私钥

    MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJFBnk78A4CN5gBpIV/pGOGqi/CzvwjvXoj2gYXtbEIg+ZxpRrVi7Is6dwIK4+xrDr35ExaN1s4GnyF3g88z93iYpM5URhQTRJ/GGENNlozkLNARRdTJfLuJxBMZHnAGOtuNTXIcIo5/k8klllBYHTqG6xIVnjRN0vsV2UGlnW7VAgMBAAECgYBMoT9xD8aRNUrXgJ7YyFIWCzEUZN8tSYqn2tPt4ZkxMdA9UdS5sFx1/vv1meUwPjJiylnlliJyQlAFCdYBo7qzmib8+3Q8EU3MDP9bNlpxxC1go57/q/TbaymWyOk3pK2VXaX+8vQmllgRZMQRi2JFBHVoep1f1x7lSsf2TpipgQJBANJlO+UDmync9X/1YdrVaDOi4o7g3w9u1eVq9B01+WklAP3bvxIoBRI97HlDPKHx+CZXeODx1xj0xPOK3HUz5FECQQCwvdagPPtWHhHx0boPF/s4ZrTUIH04afuePUuwKTQQRijnl0eb2idBe0z2VAH1utPps/p4SpuT3HI3PJJ8MlVFAkAFypuXdj3zLQ3k89A5wd4Ybcdmv3HkbtyccBFALJgs+MPKOR5NVaSuF95GiD9HBe4awBWnu4B8Q2CYg54F6+PBAkBKNgvukGyARnQGc6eKOumTTxzSjSnHDElIsjgbqdFgm/UE+TJqMHmXNyyjqbaA9YeRc67R35HfzgpvQxHG8GN5AkEAxSKOlfACUCQ/CZJovETMmaUDas463hbrUznp71uRMk8RP7DY/lBnGGMeUeeZLIVK5X2Ngcp9nJQSKWCGtpnfLQ==
    

      很明显,公钥字符串长度比较短,私钥的比较长。生成完密钥后,公钥可以存放在客户端,即使被别人知道公钥,也是没有问题的;私钥则一定要保存在服务端。如果到时公司面临人事变动,避免私钥被离职人员泄露,可以重新生成公钥和密钥。

    使用公钥加密,私钥解密

      这里在客户端模拟加密的情况,对字符串"Beyond黄家驹"使用RSA加密,调用RSAUtils的encryptByPublicKey()方法,输出结果为:

    密文: BRFjf3tUqRqlwuP5JtzxZinf7lp+AHuHM9JSabM5BNFDxuUe9+uuO6RpCHVH5PibifqQHzGNsyZn1G9QcIENT9Tbm+PZwAbNUlMPZRDBU1FSnOtY8dBdeW/lJdnY9sJVwNvIBnOLQk66hxRh6R2149dwlgdsGUpWMOMBzcP3vsU=
    

      在服务端,可以使用RSAUtils的decryptByPrivateKey()方法进行解密,现在模拟服务端解密

      在这里虽然没有完全模拟数据传输过程,比如说客户端发起一个网络请求,传递参数给服务端,服务端接收参数并进行处理,也是为了让大家可以更加容易明白,所以这里只是进行简单的模拟。可以看到android客户端端和java服务端的RSA加密解密算法是可以互通的,原因是他们所使用到的base64加密类是一致的,所以才可以实现加密和解密的算法互通。

      使用到的jar包都是javabase64-1.3.1.jar,相信不少人都知道,java中有自带的Base64算法类,但是安卓中却没有,之前出现的情况是,使用的Base64类不统一,比如在安卓客户端开发使用的Base64算法是使用第三方提供的jar包,而java服务端中使用的是JDK自带的Base64,导致从客户端传过来的密文,服务端解析出错。

      上面的例子展示了客户端使用公钥加密,服务端使用私钥解密的过程。也许你会这么想,既然可以如此,那服务端那边信息也可以通过RSA加密后,传递加密信息过来,客户端进行解密。但是,这样做,显示是不安全的。原因是,由于客户端并没有保存私钥,只有公钥,只可以服务端进行私钥加密,客户端进行公钥解密,但由于公钥是公开,别人也可以获取到公钥,如果信息被他们截取,他们同样可以通过公钥进行解密,那么这样子加密,就毫无意义了,所以这个时候,就要结合对称算法,实现客户端与服务端之前的安全通信了。

    使用AES加密解密
    加密

      模拟客户端进行AES加密,我们通过调用AESUtils中的generateKey()方法,随机产生一个密钥,用于对数据进行加密。输出的结果为:

    密钥: 6446c69c0f914a57
    密文: GECDQOsc22yV48hdJENTMg==
    
    解密

      模拟服务端进行AES解密,由于AES属于对称算法,加密和解密需要使用同一把密钥,所以,服务端要解密传递过来的内容,就需要密钥 + 密文。这里模拟一下服务端解密。

      到这里也许你会问,客户端使用AES进行加密,服务端要进行解密的话,需要用到产生的密钥,那密钥必须从客户端传输到服务端,如果不对密钥进行加密,那加密就没有意义了。所以这里终于谈到了重点,RSA算法+AES算法结合使用。

    RSA算法+AES算法的使用

      举一个简单的例子来说明一下吧,例如实名认证功能,需要传递用户真实姓名和身份证号,对于这种重要信息,需要进行加密处理。

    客户端使用RSA + AES对重要信息进行加密

    客户端加密过程主要分为以下三个步骤:

    1.客户端随机产生AES的密钥;

    2.对身份证信息(重要信息)进行AES加密;

    3.通过使用RSA对AES密钥进行公钥加密。

      这样在传输的过程中,即时加密后的AES密钥被别人截取,对其也无济于事,因为他并不知道RSA的私钥,无法解密得到原本的AES密钥,就无法解密用AES加密后的重要信息。

    服务端使用RSA + AES对重要信息进行解密

    服务端解密过程主要分为以下两个步骤:

    1.对加密后的AES密钥进行RSA私钥解密,拿到密钥原文;

    2.对加密后的重要信息进行AES解密,拿到原始内容。

      现实开发中,服务端有时也需要向客户端传递重要信息,比如登录的时候,返回token给客户端,作为令牌,这个令牌就需要进行加密,原理也是差不多的,比上面多一个步骤而已,就是将解密后的AES密钥,对将要传递给客户端的数据token进行AES加密,返回给客户端,由于客户端和服务端都已经拿到同一把AES钥匙,所以客户端可以解密服务端返回的加密后的数据。如果客户端想要将令牌进行保存,则需要使用自己定义的默认的AES密钥进行加密后保存,需要使用的时候传入默认密钥和密文,解密后得到原token。

      上面提及到客户端加密,服务端返回数据不加密的情况,上面说到仅仅使用RSA是可以,但是还是建议同时使用这两种算法,即产生一个AES密钥,使用RSA对该密钥进行公钥加密,对重要信息进行AES加密,服务端通过RSA私钥解密拿到AES密钥,再对加密后的重要信息进行解密。如果仅仅使用RSA,服务端只通过RSA解密,这样会对于性能会有所影响,原因是RSA的解密耗时约等于AES解密数据的100倍,所以如果每个重要信息都只通过RSA加密和解密,则会影响服务端系统的性能,所以建议两种算法一起使用。

    同时还有相应的JS版RSA和AES算法,使用方式也差不多,在这里简单演示一下:

    下面是一个html页面的代码,引入了rsa.js和aes.js

    <!DOCTYPE html>
    <html>
      <head>
        <title>RSA+AES.html</title>
    	
        <meta name="keywords" content="keyword1,keyword2,keyword3">
        <meta name="description" content="this is my page">
        <meta name="content-type" content="text/html; charset=UTF-8">
        <script type="text/javascript" src="./js/rsa.js"></script>
        <script type="text/javascript" src="./js/aes.js"></script>
        <script type="text/javascript">
            var key = getKey();//随机产生AES密钥
            var encryptKey = RSA(key);//对AES密钥进行RSA加密
            console.log("encryptKey: " + encryptKey);
            
            //测试AES加密和解密
            var cipherText = AESEnc(key,"123456");
            var plainText = AESDec(key,cipherText);
            console.log("密文: " + cipherText);
            console.log("明文: " + plainText);
        </script>
      </head>
      
      <body>
        This is my HTML page. <br>
      </body>
    </html>
    

    打开页面后,查看控制台输出:

    同时,模拟服务端解密,运行结果如下:

      在这里将我自己封装的RSAUtils、AESUtils以及使用第三方jar包的Base64Utils还有JS版的RSAHE AES分享给大家,希望可以帮助到大家,由于刚注册博客不久,没有多少积分,下载一些资料的时候需要积分,所以收取大家1积分,谢谢了。

    http://download.csdn.net/detail/chay_chan/9766486

    需要注意的是:

    1.RSAUtils中配置公钥和密钥,可以使用getKeys()方法产生。如果是客户端,则无须配置私钥,把没有私钥的RSAUtils放到客户端,因为仅需要用到公钥加密的方法。

    2.AESUtils中配置偏移量IV_STRING;

    3.rsa.js中最底部配置公钥,须和上面RSAUtils配置的公钥一致;

    4.aes.js中的底部var iv = CryptoJS.enc.Utf8.parse(“16-Bytes–String”); //加密向量中,替换里面的字符串,加密向量须和
    是上面的AESUtils中的偏移量一致。

      为了完成这篇博客,花费了接近半天的时间,相当于总结自己在数据传输这一方面的经验,希望可以帮助到更多的开发者,一起交流学习,互相提升和进步。

    展开全文
  • 对称算法分类及加密模式

    千次阅读 2017-03-09 22:15:48
    对称算法分类流加密(stream cipher)加密和解密双方使用相同伪随机加密数据流(即密钥),一般都是逐位异或或者随机置换数据内容,常见的流加密算法如RC4。 流加密中,密钥的长度和明文的长度是一致的。假设明文的...
  • 在上一篇文章【算法大杂烩】常见算法的归类和总结——对称加密算法 中我们简要介绍了常见的对称加密... 常见的非对称算法哪些以及它们的特性和区别是什么? 非对称加密算法的应用场景有哪些? 非对称加密算法  ...
  • 对称与非对称加密算法

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

    2020-03-03 23:37:35
    对称加密算法封装的函数系列名字是以EVP_Encrypt*...*开头的,其实,这些函数只是简单调用了EVP_Cipher*...*系列的同名函数,换一个名字可能是为了更好的区别和理解。除了实现了对称加密算法外,EVP_Encrypt*...*...
  • 一、对称加密算法   指加密和解密使用相同密钥的加密算法对称加密算法用来对敏感数据等信息进行加密,常用的算法包括DES、3DES、AES、DESX、Blowfish、、RC4、RC5、RC6。  DES(Data Encryption Standard):...
  • 常用的对称加密算法:AES,RC4,3DES 传输的示意图如下所示: 第二 、非对称加密: 非对称加密算法实现机密信息交换的基本过程是: 甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开; 得到该公用密钥的...
  • java 非对称加密算法

    千次阅读 2017-05-23 21:24:36
    慕课网学习笔记 参考:java加密算法 ...非对称加密算法主要有:DH(Diffie-Hellman)密钥交换算法、RSA(基于因子分解)、Elgamal(基于离散对数)、ECC(Elliptical Curve Cryptography,椭圆曲线加密)。DH(密
  • 笔者在前面几篇文章中,一口气分别介绍了【对称加密算法、非对称加密算法、信息摘要算法】,从中读者能大致了解到... 为什么数字签名采用非对称算法和信息摘要算法? 数字签名的操作步骤是什么? 消息验签的操作...
  • 对称加密算法RSA 学习

    千次阅读 多人点赞 2018-10-17 17:49:28
    对称加密算法RSA 学习 RSA加密算法是一种非对称加密算法。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工...
  • 密码学安全算法--对称加密算法

    千次阅读 2017-06-04 21:45:50
    最常见对称加密算法是:DES、3DES、AES、RC4。 对称加密算法基本原理 先上图,对称加密工作过程 在整个工作过程中涉及到以下几个概念 - 明文:也就是原始信息或者说原始数据。也就是上图中的A。 - 加密算法...
  • 对称加密算法DES

    千次阅读 2011-12-07 17:17:26
    1.理解对称加密算法的原理和特点 2.理解DES算法的加密原理 实验基础: 什么是对称密码 根据密码算法所用的密钥数量,我们根据加密算法与解密算法所用的密钥是否相同,或是否能简单地由加/解密密钥导出解/加密...
  • 笔者在学习和工作中,经常跟【算法】打交道... 对称加密算法,顾名思义,就是算法的执行过程是对称的;用最简单的话说,就是加密方和解密方使用的密钥是一致的,只不过执行的过程是相反的,一方(A)对明文(P)使...
  • 加密目前已经成为计算机安全研究的主要方向,一个密码系统的安全性主要在于密钥的保密性,而不是算法的保密性。 加密系统至少要包括如下四个部分 1 未加密的报文,也叫明文:用M(消息)或P(明文)表示,可以是...
  • 对称加密算法原理简介

    千次阅读 2020-03-15 16:41:41
    对称加密算法原理简介 对称加密算法使用相同的密钥进行加密和解密,它的计算量小,速度快,是最常用的加密方式,也是密码学和各种安全技术应用的基础。本文主要介绍对称加密算法的基本概念、设计思想和原理。 为什么...
  • 对称加密算法

    2010-02-05 17:37:00
    文档创建于:2010-02-05 [以下内容来自百度百科]http://baike.baidu.com/view/1490349.htm?fr=ala0_1非对称加密算法  asymmetric encoding algorithm 非对称加密算法需要两个密钥:公开密钥(publickey)...
  • 对称加密算法-PBE算法

    万次阅读 2011-03-30 22:33:00
    一、简述  PBE算法(Password Base Encryption,基于口令加密)算法是一种基于口令的加密算法。特点在于口令由用户自己掌握,采用随机数(我们这里叫做 盐)杂凑多重加密等方法保证数据的安全性。 ...
  • 加密分为两大类:对称加密、非对称加密,两类加密算法各有优点,在不同的场景使用不同的算法对称加密 加密方将原始数据和加密密钥一起经过特殊加密算法处理后,生成密文结果,解密方使用相同的秘钥及相同加密...
  • 【★】RSA-什么是不对称加密算法

    千次阅读 2018-01-05 11:01:48
    对称加密算法RSA浅析 本文主要介绍不对称加密算法中最精炼的RSA算法。我们先说结论,也就是RSA算法怎么算,然后再讲为什么。 随便选取两个不同的大素数p和q,N=p*q,r=(p-1)*(q-1)。 算出一组(e,d)...
  • 常见对称加密算法与工作模式简介

    千次阅读 2019-04-07 22:15:40
    ... 对称密码(Symmetric Cipher)算法又叫传统密码算法,加密密钥能够从...对称算法的安全性依赖于密钥,所以密钥的保密性对通信的安全性至关重要;在安全通信之前,需要有一个安全通道以商定密钥。 加密和解密...
  • 对称加密算法--Diffie-Hellman算法

    千次阅读 2019-03-10 21:29:00
    对称加密算法又称公开密钥加密算法,非对称加密是相对于对称加密而言的,对称加密指的是通信双方使用的密钥是一致的,而非对称加密就是算法使用的密钥不一致。非对称加密的好处是当通信双方没有事先协商密钥的情况...
  • 解读国密非对称加密算法SM2

    千次阅读 2021-01-21 16:44:37
    本文先介绍非对称加密算法,然后聊一聊椭圆曲线密码算法(Elliptic Curve Cryptography,ECC),最后才是本文的主题国密非对称加密算法SM2。因为我的数学知识有限,对于算法涉及的一些复杂的理论知识,也是不懂,...
  • RSA非对称加密算法详解

    万次阅读 多人点赞 2019-01-28 17:11:57
    RSA加密算法是最常用的非对称加密算法,由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)于1977年一起提出,RSA就是他们三人姓氏开头字母拼在一起组成的。非对称...
  • 一、引言 今天我们来聊一聊一个有趣的话题。 小编在目前公司工作两年之余,主要接触的是...众所周知,HTTPS协议大家认为它是安全的,数据会被加密,那么今天小编就针对HTTPS来延伸出对称性加密以及非对称性加密...
  • 对称算法之证书常用资料整理

    千次阅读 2019-06-25 09:28:03
    1. 对称密码的局限性 密钥分发问题:必须保证传输密钥的信道足够安全 密钥量问题:每两人都需要一对密钥,密钥量太大 数字签名问题:接收方可以伪造签名,发送方可以否认发送过的消息 无法解...
  • RSA ~ 非对称加密算法

    万次阅读 多人点赞 2016-12-06 10:10:50
    RSA:  非对称加密,加密与解密使用的密钥不是同一密钥,对中一个对外公开,称为公钥,另一个只有所有者知道,称为...对称加密算法不能实现签名,因此签名只能非对称算法。 RSA算法非常简单,概述如下:

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 66,530
精华内容 26,612
关键字:

以下属于对称算法的是