精华内容
下载资源
问答
  • sha256算法 位数
    千次阅读
    2020-01-11 15:04:44

    概述

    对于任意长度的消息,SHA256都会产生一个256位的哈希值,称作消息摘要。这个摘要相当于四个长度为32个字节的数组,通常有一个长度为64的十六进制字符串来表示,其中1个字节=8位,一个十六进制的字符的长度为4位。
    总体上,HSA256与MD4、MD5以及HSA-1等哈希函数的操作流程类似,待哈希的消息在继续哈希计算之前首先要进行以下两个步骤:

    • 对消息进行补位处理,是的最终的长度是512位的倍数
    • 然后以512位为单位对消息进行分块为M(1), M(2),…M(N)
    • 消息区块将进行逐个处理:从一个固定的初始哈希H(0)开始,进行以下序列的计算:
      H(i) = H(i-1) + CM(i)(H(i-1))
      其中C是SHA256的压缩函数,+是mod 232加法,即将两个数字加在一起。
    • 针对每一个消息M,都将其hash为长度为64位的16进制表示,既H。
    更多相关内容
  • sha256算法细节详解

    千次阅读 2022-04-05 21:44:18
    sha256算法

    最近在项目中遇到sha256算法加密的需求,于是看了一些相关的资料,最后也整理出一些东西,并且参考文档自己实现了一遍:

    #define S(a, b)     (((a) >> (b)) | ((a) << (32 - b)))  /* a循环右移b位 */
    
    /* sha256逻辑函数 */
    #define CH(x, y, z) ((x & y) ^ ((~x) & z))
    #define MA(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
    #define Σ0(x)       (S(x, 2)^S(x, 13)^S(x, 22))
    #define Σ1(x)       (S(x, 6)^S(x, 11)^S(x, 25))
    #define σ0(x)       (S(x, 7)^S(x, 18)^(x >> 3))
    #define σ1(x)       (S(x, 17)^S(x, 19)^(x >> 10))
    
    /*	功能:大小端判断
    	返回: 1小端  0大端  */
    int Endian()
    {
    	int a = 1;
    	int *p = &a;
    
    	return (*(char *)p == 1);
    }
    /*  功能:sha256编码
    	入参:
    	char *Src 源数据  
    	int SrcLen 源数据长度
    	返回值: sha256数据  */
    char* MyShaA256Encode(const char *Src, long long SrcLen)
    {
    	unsigned long i = 0, T1 = 0, T2 = 0, A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 0;
    	unsigned long *p = NULL;
    	unsigned long W[64] = {0};     /* 64个字 */
    	static char shadata[256] = {0};  /* sha256数据缓存 */
    	unsigned long Key[64] =    /* 秘钥表 */
    	{
                0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
                0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
                0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
                0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
                0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
                0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
                0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
                0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
        };
    	unsigned long Hash[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};    /* 初始哈希值 */
    	long long reallen = (SrcLen * 8) % 512 >= 448 ? ((SrcLen * 8) / 512 + 2) * 64 : ((SrcLen * 8) / 512 + 1) * 64;   /* 补位后长度 */
    	char * processsrc = (char *)calloc(reallen, sizeof(char));    /* 源数据补位后缓存 */
    	if (NULL == processsrc) {
    		return NULL;
    	}
    
    	/* 预处理 */
    	if (Endian()) {
    		for (i = 0; i < SrcLen; processsrc[i + 3 - 2 * (i % 4)] = Src[i], i++);  /* 小端存法 */
    		processsrc[i + 3 - 2 * (i % 4)] = 1 << 7;  /* 补一个1 */
    	} else {
    		memcpy(processsrc, Src, SrcLen);    /* 大端存法 */
    		*(processsrc + SrcLen) = 1 << 7;    /* 补一个1 */
    	}
    	*((long*)(processsrc + reallen - 4)) = SrcLen << 3;   /* 最后64位代表源数据长度 */
    	*((long*)(processsrc + reallen - 8)) = SrcLen >> 29;
    
    	for (p = (unsigned long *)processsrc; p < (unsigned long *)(processsrc + reallen); p += 16) {
    		/* 初始化64个字(W) */
    		for (i = 0; i < 16; ++i) {
    			W[i] = *(p + i);
    		}
    		for (i = 16; i < 64; ++i) {
    			W[i] = σ1(W[i - 2]) + W[i - 7] + σ0(W[i - 15]) + W[i - 16];
    		}
    
    		/* sha256摘要迭代 */
    		A = Hash[0]; B = Hash[1]; C = Hash[2]; D = Hash[3]; E = Hash[4]; F = Hash[5]; G = Hash[6]; H = Hash[7]; 
    		for (i = 0; i < 64; ++i) {
    			T1 = H + Σ1(E) + CH(E, F, G) + Key[i] + W[i];
    			T2 = Σ0(A) + MA(A, B, C);
    			H = G, G = F, F = E, E = D + T1, D = C, C = B, B = A, A = T1 + T2;
    		}
    		Hash[0] += A, Hash[1] += B, Hash[2] += C, Hash[3] += D, Hash[4] += E, Hash[5] += F, Hash[6] += G, Hash[7] += H;
    	}
    
        sprintf(shadata, "%08X%08X%08X%08X%08X%08X%08X%08X", Hash[0], Hash[1], Hash[2], Hash[3], Hash[4], Hash[5], Hash[6], Hash[7]);
    	free(processsrc);
    	printf("sha256: %s\r\n", shadata);
    
    	return shadata;
    }
    

    源码详解:

    1、sha256常数

    sha256最终输出的是64位字符串,故需要一串64字符的初始哈希值,即源码中的Hash[8],刚好是8*8个字符,其次还需要64个4byte的秘钥,用于摘要迭代,即源码中的Key[64]:

        unsigned long Key[64] =    /* 秘钥表 */
    	{
                0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
                0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
                0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
                0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
                0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
                0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
                0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
                0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
        };
    	unsigned long Hash[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};    /* 初始哈希值 */
    
    2、补位后长度计算

    补位后长度计算遵循这样的原则:在源数据后先添加一位1,再在1后面添加若干个0,知道数据总位数对512求余为512-64=448,最后64位需要填写源数据长度,用于入参SrcLen表示的是原字符串长度(单位是byte),1byte=8bit,所以在计算时需要有*8的操作,具体如下:

    long long reallen = (SrcLen * 8) % 512 >= 448 ? ((SrcLen * 8) / 512 + 2) * 64 : ((SrcLen * 8) / 512 + 1) * 64;   /* 补位后长度 */
    
    3、预处理(补位)

    将原始数据Src扩展成512位对齐的processsrc数据,此处需要关注的是Src数据默认是低地址->高地址排列传入的,假设需要加密的数据是字符串"12345",传入的是字符串首地址,长度为5byte,这个方法内部看到的是0x31,0x32,0x33,0x34,0x35这些数据,接着以4字节为单位进行加工,首先是0x31323334,将这个数据看成是一个4byte的整体,从低地址到高地址依次存入processsrc,小端机器按0x34,0x33,0x32,0x31存入,大端机器按0x31,0x32,0x33,0x34存入(此步其他数文章里没有提出,本人也不确定是不是这样??),小端最后就是这行代码:

    for (i = 0; i < SrcLen; processsrc[i + 3 - 2 * (i % 4)] = Src[i], i++);
    

    大端是这行代码:

    memcpy(processsrc, Src, SrcLen);
    

    将源数据存入后,再进行1+n个0的补齐,calloc初始值就是0,所以只需要补齐一个1:,小端补1:

    processsrc[i + 3 - 2 * (i % 4)] = 1 << 7;
    

    大端补1:

    *(processsrc + SrcLen) = 1 << 7;
    

    最后64位代表源数据长度,继续补齐:

    *((long*)(processsrc + reallen - 4)) = SrcLen << 3; 
    *((long*)(processsrc + reallen - 8)) = SrcLen >> 29;
    
    4、初始化64个字

    将每个512位的数据块扩充成64byte,前16个byte将512位数据完全拷贝即可,后面48byte参考文档里面这个公式扩充:
    在这里插入图片描述
    相应的代码是这段:

    		for (i = 0; i < 16; ++i) {
    			W[i] = *(p + i);
    		}
    		for (i = 16; i < 64; ++i) {
    			W[i] = σ1(W[i - 2]) + W[i - 7] + σ0(W[i - 15]) + W[i - 16];
    		}
    
    5、摘要迭代

    根据官方手册上提供的逻辑图进行操作即可:
    在这里插入图片描述
    代码是这一段:

    		A = Hash[0]; B = Hash[1]; C = Hash[2]; D = Hash[3]; E = Hash[4]; F = Hash[5]; G = Hash[6]; H = Hash[7]; 
    		for (i = 0; i < 64; ++i) {
    			T1 = H + Σ1(E) + CH(E, F, G) + Key[i] + W[i];
    			T2 = Σ0(A) + MA(A, B, C);
    			H = G, G = F, F = E, E = D + T1, D = C, C = B, B = A, A = T1 + T2;
    		}
    		Hash[0] += A, Hash[1] += B, Hash[2] += C, Hash[3] += D, Hash[4] += E, Hash[5] += F, Hash[6] += G, Hash[7] += H;
    

    接下来就是重复4、5步操作,直到将processsrc 的数据完全处理完,得到一串Hash即sha256的加密数据。

    展开全文
  • SHA256算法原理及其实现

    千次阅读 2021-07-19 10:14:40
    SHA家族的五个算法,分别是SHA-1、SHA-224、SHA-256SHA-384,和SHA-512,由美国国家安全局(NSA)所规划,并由美国国家规范与技能研究院(NIST)发布。 该算法是美国的政府规范算法,后四者有时并称为SHA-2。 SHA...

    SHA家族的五个算法,分别是SHA-1、SHA-224、SHA-256、SHA-384,和SHA-512,由美国国家安全局(NSA)所规划,并由美国国家规范与技能研究院(NIST)发布。
    该算法是美国的政府规范算法,后四者有时并称为SHA-2。
    SHA在很多安全协定中广为运用,包含TLS和SSL、PGP、SSH、S/MIME和IPsec,曾被视为是MD5(更早之前被广为运用的杂凑函数)的后继者。 但SHA-1的安全性现在被密码学家严峻质疑,有学者曾经爆出NSA在SHA-1留下的后门。
    虽然至今尚未出现对SHA-2有效的攻击,但是它的算法跟SHA-1基本上仍然相似,因此有些人开始发展其他替代的杂凑算法。

    一文读懂SHA256算法原理及其实现

    学习区块链,总是无法避开各种加密算法,因为各种加密算法在实现区块链当中的各个环节都有着不可替代的作用。这里介绍一下在比特币挖矿以及merkle树当中被大量使用的鼎鼎大名的SHA256算法。

    SHA-2 族算法简介

    一个n位的哈希函数就是一个从任意长的消息到n位哈希值的映射,一个n位的加密哈希函数就是一个单向的、避免碰撞的n位哈希函数。这样的函数是目前在数字签名和密码保护当中极为重要的手段。

    当前比较流行的哈希函数主要有128位的MD4和MD5和160位的SHA-1,今天介绍的SHA-2族有着更多位的输出哈希值,破解难度更大,能够提高更高的安全性。

    SHA-2,名称来自于安全散列算法2(英语:Secure Hash Algorithm 2)的缩写,一种密码散列函数算法标准,由美国国家安全局研发,由美国国家标准与技术研究院(NIST)在2001年发布。属于SHA算法之一,是SHA-1的后继者。其下又可再分为六个不同的算法标准,包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。

    这些变体除了生成摘要的长度、循环运行的次数等一些细微差异之外,基本结构是一致的。本文主要讲一讲SHA256。

    SHA256原理详解

    概述

    对于任意长度的消息,SHA256都会产生一个256位的哈希值,称作消息摘要。这个摘要相当于是个长度为32个字节的数组,通常有一个长度为64的十六进制字符串来表示,其中1个字节=8位,一个十六进制的字符的长度为4位。

    来看一个具体的例子:

    BlockChain

    这句话经过哈希函数SHA256后得到的哈希值为:

    3a6fed5fc11392b3ee9f81caf017b48640d7458766a8eb0382899a605b41f2b9

    总体上,HSA256与MD4、MD5以及HSA-1等哈希函数的操作流程类似,待哈希的消息在继续哈希计算之前首先要进行以下两个步骤:

    • 对消息进行补位处理,是的最终的长度是512位的倍数,然后
    • 以512位为单位对消息进行分块为

     

     消息区块将进行逐个处理:从一个固定的初始哈希开始,进行以下序列的计算:

     

    其中是SHA256的压缩函数,是mod 加法,即将两个数字加在一起,如果对取余, 是消息区块的哈希值.

    算法详细描述

    SHA256的压缩函数主要对512位的消息区块和256位的中间哈希值进行操作,本质上,它是一个通过将消息区块为密钥对中间哈希值进行加密的256位加密算法。 因此,为了描述SHA256算法,有以下两方面的组件需要描述:

    • SHA256压缩函数
    • SHA256消息处理流程

    以下的描述当中所使用到的标记如下:

    • : 按位异或
    • : 按位与
    • : 按位或
    • : 补位
    • : 相加以后对求余
    • : 右移n位
    • : 循环右移n位

    以上所有的操作都是针对32位字节.

    常量初始化

    初始哈希值取自自然数中前面8个素数(2,3,5,7,11,13,17,19)的平方根的小数部分, 并且取前面的32位. 下面举个例子: 小数部分约为0.414213562373095048, 而其中

    于是, 质数2的平方根的小数部分取前32位就对应0x6a09e667.

    如此类推, 初始哈希值由以下8个32位的哈希初值构成:

    SHA256算法当中还使用到64个常数, 取自自然数中前面64个素数的立方根的小数部分的前32位, 如果用16进制表示, 则相应的常数序列如下:

    428a2f98 71374491 b5c0fbcf e9b5dba5
    3956c25b 59f111f1 923f82a4 ab1c5ed5
    d807aa98 12835b01 243185be 550c7dc3
    72be5d74 80deb1fe 9bdc06a7 c19bf174
    e49b69c1 efbe4786 0fc19dc6 240ca1cc
    2de92c6f 4a7484aa 5cb0a9dc 76f988da
    983e5152 a831c66d b00327c8 bf597fc7
    c6e00bf3 d5a79147 06ca6351 14292967
    27b70a85 2e1b2138 4d2c6dfc 53380d13
    650a7354 766a0abb 81c2c92e 92722c85
    a2bfe8a1 a81a664b c24b8b70 c76c51a3
    d192e819 d6990624 f40e3585 106aa070
    19a4c116 1e376c08 2748774c 34b0bcb5
    391c0cb3 4ed8aa4a 5b9cca4f 682e6ff3
    748f82ee 78a5636f 84c87814 8cc70208
    90befffa a4506ceb bef9a3f7 c67178f2

    消息预处理

    在计算消息的哈希摘要之前需要对消息进行预处理:

    • 对消息进行补码处理: 假设消息的二进制编码长度为位. 首先在消息末尾补上一位"1", 然后再补上个"0", 其中为下列方程的最小非负整数

    举个例子, 以消息"abc"为例显示补位的过程.

    a,b,c对应的ASCII码和二进制编码分别如下:

    原始字符    ASCII码    二进制编码
    a          97         01100001
    b          98         01100010
    c          99         01100011

    因此, 原始信息"abc"的二进制编码为:01100001 01100010 01100011, 第一步补位, 首先在消息末尾补上一位"1", 结果为: 01100001 01100010 01100011 1; 然后进行第二步的补位, 因为, 可以得到, 在第一步补位后的消息后面再补423个"0", 结果如下:

    最后还需要在上述字节串后面继续进行补码, 这个时候补的是原消息"abc"的二进制长度的64位二进制表示形式, 补完以后的结果如下:

    最终补完以后的消息二进制位数长度是512的倍数.

    这里需要注意的两点是不管原来的消息长度是多少, 即使长度已经满足对512取模后余数是448,补位也必须要进行,这时要填充512位. 另外, 考虑到最后要将消息长度转换为64位二进制编码, 因此, 长度的必须小于, 绝大多数情况, 这个足够大了.

    • 将补码处理后的消息以512位为单位分块为: , 其中第个消息块的前32位表示为: , 后面32位为: , 以此类推, 最后32位的消息块可表示为: . 我们采用Big endian约定对数据进行编码, 即认为第一个字节是最高位字节, 因此, 对于每一个32位字节, 最最左边的比特是最大的比特位.

    摘要计算主循环

    哈希计算算法如下:

    •  ( = 补码后消息块个数)
      • 用第个中间哈希值来对 进行初始化, 当时, 就使用初始化哈希, 即:

    • 应用SHA256压缩函数来更新
        • 计算(具体定义如下)

    • 计算第个中间哈希值

    • 为最终需要的哈希。

    逻辑函数定义

    SHA256算法当中所使用到的6个逻辑函数如下:每个函数都对32位字节进行操纵,并输出32位字节。

    扩展消息块通过以下方式进行计算:

    图形表示

    SHA256压缩函数的图形表示如下:

    扩展消息块的求解算法可以表示如下:

    SHA伪代码

    Note 1: All variables are 32 bit unsigned integers and addition is calculated modulo 232
    Note 2: For each round, there is one round constant k[i] and one entry in the message schedule array w[i], 0 ≤ i ≤ 63
    Note 3: The compression function uses 8 working variables, a through h
    Note 4: Big-endian convention is used when expressing the constants in this pseudocode,
        and when parsing message block data from bytes to words, for example,
        the first word of the input message "abc" after padding is 0x61626380
    
    Initialize hash values:
    (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
    h0 := 0x6a09e667
    h1 := 0xbb67ae85
    h2 := 0x3c6ef372
    h3 := 0xa54ff53a
    h4 := 0x510e527f
    h5 := 0x9b05688c
    h6 := 0x1f83d9ab
    h7 := 0x5be0cd19
    
    Initialize array of round constants:
    (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
    k[0..63] :=
       0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
       0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
       0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
       0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
       0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
       0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
       0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
       0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
    
    Pre-processing (Padding):
    begin with the original message of length L bits
    append a single '1' bit
    append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512
    append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bits
    
    Process the message in successive 512-bit chunks:
    break message into 512-bit chunks
    for each chunk
        create a 64-entry message schedule array w[0..63] of 32-bit words
        (The initial values in w[0..63] don't matter, so many implementations zero them here)
        copy chunk into first 16 words w[0..15] of the message schedule array
    
        Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array:
        for i from 16 to 63
            s0 := (w[i-15] rightrotate  7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift  3)
            s1 := (w[i- 2] rightrotate 17) xor (w[i- 2] rightrotate 19) xor (w[i- 2] rightshift 10)
            w[i] := w[i-16] + s0 + w[i-7] + s1
    
        Initialize working variables to current hash value:
        a := h0
        b := h1
        c := h2
        d := h3
        e := h4
        f := h5
        g := h6
        h := h7
    
        Compression function main loop:
        for i from 0 to 63
            S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25)
            ch := (e and f) xor ((not e) and g)
            temp1 := h + S1 + ch + k[i] + w[i]
            S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22)
            maj := (a and b) xor (a and c) xor (b and c)
            temp2 := S0 + maj
     
            h := g
            g := f
            f := e
            e := d + temp1
            d := c
            c := b
            b := a
            a := temp1 + temp2
    
        Add the compressed chunk to the current hash value:
        h0 := h0 + a
        h1 := h1 + b
        h2 := h2 + c
        h3 := h3 + d
        h4 := h4 + e
        h5 := h5 + f
        h6 := h6 + g
        h7 := h7 + h
    
    Produce the final hash value (big-endian):
    digest := hash := h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7

    SHA256代码实现

    下面是基于上述伪代码用go语言对SHA256进行的实现.

    package main
    
    import (
    	"encoding/binary"
    )
    
    func wikiSha256(message []byte) [32]byte {
        //初始哈希值
    	h0 := uint32(0x6a09e667)
    	h1 := uint32(0xbb67ae85)
    	h2 := uint32(0x3c6ef372)
    	h3 := uint32(0xa54ff53a)
    	h4 := uint32(0x510e527f)
    	h5 := uint32(0x9b05688c)
    	h6 := uint32(0x1f83d9ab)
    	h7 := uint32(0x5be0cd19)
        
        //计算过程当中用到的常数
    	k := [64]uint32{
                    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
    		0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
    		0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    		0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    		0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    		0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    		0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    		0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}
        
    	padded := append(message, 0x80)
    	if len(padded) % 64 < 56 {
    		suffix := make([]byte, 56 - (len(padded) % 64))
    		padded = append(padded, suffix...)
    	} else {
    		suffix := make([]byte, 64 + 56 - (len(padded) % 64))
    		padded = append(padded, suffix...)
    	}
    	msgLen := len(message) * 8
    	bs := make([]byte, 8)
    	binary.BigEndian.PutUint64(bs, uint64(msgLen))
    	padded = append(padded, bs...)
    
    	broken := [][]byte{};
        
    	for i := 0; i < len(padded) / 64; i++ {
    		broken = append(broken, padded[i * 64: i * 64 + 63])
    	}
        
        //主循环
    	for _, chunk := range broken {
    		w := []uint32{}
            
    		for i := 0; i < 16; i++ {
    			w = append(w, binary.BigEndian.Uint32(chunk[i * 4:i * 4 + 4]))
    		}
    		w = append(w, make([]uint32, 48)...)
            
            //W消息区块处理
    		for i := 16; i < 64; i++ {
    			s0 := rightRotate(w[i - 15], 7) ^ rightRotate(w[i - 15], 18) ^ (w[i - 15] >> 3)
    			s1 := rightRotate(w[i - 2], 17) ^ rightRotate(w[i - 2], 19) ^ (w[i - 2] >> 10)
    			w[i] = w[i - 16] + s0 + w[i - 7] + s1
    		}
    
    		a := h0
    		b := h1
    		c := h2
    		d := h3
    		e := h4
    		f := h5
    		g := h6
    		h := h7
            
            //应用SHA256压缩函数更新a,b,...,h
    		for i := 0; i < 64; i++ {
    			S1 := rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25)
    			ch := (e & f) ^ ((^e) & g)
    			temp1 := h + S1 + ch + k[i] + w[i]
    			S0 := rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22)
    			maj := (a & b) ^ (a & c) ^ (b & c)
    			temp2 := S0 + maj
    
    			h = g
    			g = f
    			f = e
    			e = d + temp1
    			d = c
    			c = b
    			b = a
    			a = temp1 + temp2
    		}
            
    		h0 = h0 + a
    		h1 = h1 + b
    		h2 = h2 + c
    		h3 = h3 + d
    		h4 = h4 + e
    		h5 = h5 + f
    		h6 = h6 + g
    		h7 = h7 + h
    	}
    	hashBytes := [][]byte{iToB(h0), iToB(h1), iToB(h2), iToB(h3), iToB(h4), iToB(h5), iToB(h6), iToB(h7)}
    	hash := []byte{}
    	hashArray := [32]byte{}
    	for i := 0; i < 8; i ++ {
    		hash = append(hash, hashBytes[i]...)
    	}
    	copy(hashArray[:], hash[0:32])
    	return hashArray
    }
    
    func iToB(i uint32) []byte {
    	bs := make([]byte, 4)
    	binary.BigEndian.PutUint32(bs, i)
    	return bs
    }
    
    //循环右移函数
    func rightRotate(n uint32, d uint) uint32 {
    	return (n >> d) | (n << (32 - d))
    }
    展开全文
  • SHA256算法 sha256与md5一样是散列算法,不是加密算法,不存在解密的问题,因此是不可逆的,可以通过key+password,对密码进行加密,在后台进行比对,安全性比md5高一点,加密后生成的密文为64位,而md5为32位;此外...

    SHA256算法

    sha256与md5一样是散列算法,不是加密算法,不存在解密的问题,因此是不可逆的,可以通过key+password,对密码进行加密,在后台进行比对,安全性比md5高一点,加密后生成的密文为64位,而md5为32位;此外还可以使用sha512安全性相对更高一些,密文为128位。

    前端使用
    vue引入npm install js-sha256
    下载地址为:https://cdnjs.cloudflare.com/ajax/libs/js-sha256/0.9.0/sha256.jshttps://cdnjs.cloudflare.com/ajax/libs/js-sha256/0.9.0/sha256.min.js

    // If you use node.js, you should require the module first:
    // var sha256 = require('js-sha256');
    // or TypeScript
    import { sha256, sha224 } from 'js-sha256';
    function randomString(e) {  
      e = e || 32;  //e为随机码位数
      var t = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
      a = t.length;
      n = "";
      for (i = 0; i < e; i++){
         n += t.charAt(Math.floor(Math.random() * a));
      }
      return n;
    }
    var key=randomString(16);  //加密传入后台
    var enctyptData = sha256(key+password);  //前台页面输入的密码
    // var enctyptData = sha256.hex(key+password);  支持中英文 数组 sha256()和sha256.hex()密文一致
    

    java后端使用

    String decryptData = DigestUtils.sha256Hex(key+password);  //从前端传入的密码,key为解密后的key值
    

    以上可看出在使用sha256算法进行加密时,前后台同时需要key值,为了保证前后台在传输key的过程中安全性更高,使得key值不被泄露,因此可以使用ras加密算法对key值进行加密。

    RSA算法

    RSA算法是一种非对称的加密算法,通过生成一对私钥密钥进行加解密,后台将私钥进行存储在session中,将公钥传到前台进行关键值加密,将加密之后的密文传往后台,通过使用私钥进行解密,因此rsa算法是可逆的,通常用于对key值进行加解密,与AES算法结合使用,保证系统的安全性。
    前台使用
    vue引入 npm install jsencrypt
    或下载地址(jsencrypt.js / jsencrypt.min.js)为:https://github.com/travist/jsencrypt/blob/master/bin/jsencrypt.js

    <!doctype html>
    <html>
      <head>
        <title>JavaScript RSA Encryption</title>
        <script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
        <script src="bin/jsencrypt.min.js"></script>
        <script type="text/javascript">
    
          // Call this code when the page is done loading.
          $(function() {
    
            // Run a quick encryption/decryption when they click.
            $('#testme').click(function() {
    
              // Encrypt with the public key...
              var encrypt = new JSEncrypt();
              encrypt.setPublicKey($('#pubkey').val());
              var encrypted = encrypt.encrypt($('#key').val());
    
              // Decrypt with the private key...
              var decrypt = new JSEncrypt();
              decrypt.setPrivateKey($('#privkey').val());
              var decryptedkey = decrypt.decrypt(encrypted);
    
              // Now a simple check to see if the round-trip worked.
              if (decryptedkey == $('#input').val()) {
                alert('It works!!!');
              }
              else {
                alert('Something went wrong....');
              }
            });
          });
        </script>
      </head>
      <body>
        <label for="privkey">Private Key</label><br/>
        <textarea id="privkey" rows="15" cols="65">
       						     -----BEGIN RSA PRIVATE KEY-----
    				MIICXQIBAAKBgQDlOJu6TyygqxfWT7eLtGDwajtNFOb9I5XRb6khyfD1Yt3YiCgQ
    				WMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76xFxdU6jE0NQ+Z+zEdhUTooNR
    				aY5nZiu5PgDB0ED/ZKBUSLKL7eibMxZtMlUDHjm4gwQco1KRMDSmXSMkDwIDAQAB
    				AoGAfY9LpnuWK5Bs50UVep5c93SJdUi82u7yMx4iHFMc/Z2hfenfYEzu+57fI4fv
    				xTQ//5DbzRR/XKb8ulNv6+CHyPF31xk7YOBfkGI8qjLoq06V+FyBfDSwL8KbLyeH
    				m7KUZnLNQbk8yGLzB3iYKkRHlmUanQGaNMIJziWOkN+N9dECQQD0ONYRNZeuM8zd
    				8XJTSdcIX4a3gy3GGCJxOzv16XHxD03GW6UNLmfPwenKu+cdrQeaqEixrCejXdAF
    				z/7+BSMpAkEA8EaSOeP5Xr3ZrbiKzi6TGMwHMvC7HdJxaBJbVRfApFrE0/mPwmP5
    				rN7QwjrMY+0+AbXcm8mRQyQ1+IGEembsdwJBAN6az8Rv7QnD/YBvi52POIlRSSIM
    				V7SwWvSK4WSMnGb1ZBbhgdg57DXaspcwHsFV7hByQ5BvMtIduHcT14ECfcECQATe
    				aTgjFnqE/lQ22Rk0eGaYO80cc643BXVGafNfd9fcvwBMnk0iGX0XRsOozVt5Azil
    				psLBYuApa66NcVHJpCECQQDTjI2AQhFc1yRnCU/YgDnSpJVm1nASoRUnU8Jfm3Oz
    				uku7JUXcVpt08DFSceCEX9unCuMcT72rAQlLpdZir876
    						    -----END RSA PRIVATE KEY-----
    	</textarea><br/>
        <label for="pubkey">Public Key</label><br/>
        <textarea id="pubkey" rows="15" cols="65">
    			              -----BEGIN PUBLIC KEY-----
    			MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlOJu6TyygqxfWT7eLtGDwajtN
    			FOb9I5XRb6khyfD1Yt3YiCgQWMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76
    			xFxdU6jE0NQ+Z+zEdhUTooNRaY5nZiu5PgDB0ED/ZKBUSLKL7eibMxZtMlUDHjm4
    			gwQco1KRMDSmXSMkDwIDAQAB
    			              -----END PUBLIC KEY-----
    </textarea><br/>
        <label for="key">Text to encrypt:</label><br/>
        <textarea id="key" name="input" type="text" rows=4 cols=70>This is a test!</textarea><br/>
        <input id="testme" type="button" value="Test Me!!!" /><br/>
      </body>
    </html>
    

    后台使用
    生成私钥密钥对+加解密数据

    package RSA;
     
    import java.io.ByteArrayOutputStream;
    import java.security.Key;
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.SecureRandom;
    import java.security.Signature;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
     
    import javax.crypto.Cipher;
     
    import org.apache.commons.collections.set.SynchronizedSet;
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
     
    public class RSAUtils {
        public static final String KEY_ALGORITHM = "RSA";
     
        private static final String PUBLIC_KEY = "RSAPublicKey";
     
        private static final String PRIVATE_KEY = "RSAPrivateKey";
     
        public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
        /**
         * RSA最大加密明文大小
         * */
        private static final int MAX_ENCRYPT_BLOCK = 117;
     
        /**
        * RSA最大解密密文大小
         */
        private static final int MAX_DECRYPT_BLOCK = 128;
     
        private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
     
        //获得公钥字符串
        public static String getPublicKeyStr(Map<String, Object> keyMap) throws Exception {
            //获得map中的公钥对象 转为key对象
            Key key = (Key) keyMap.get(PUBLIC_KEY);
            //编码返回字符串
            return bytesToHex(encryptBASE64(key.getEncoded()).getBytes());
        }
     
        //获得私钥字符串
        public static String getPrivateKeyStr(Map<String, Object> keyMap) throws Exception {
            //获得map中的私钥对象 转为key对象
            Key key = (Key) keyMap.get(PRIVATE_KEY);
            //编码返回字符串
            return bytesToHex(encryptBASE64(key.getEncoded()).getBytes());
        }
     
     
        //获取公钥
        public static PublicKey getPublicKey(String key) throws Exception {
            byte[] keyBytes;
            keyBytes = (new BASE64Decoder()).decodeBuffer(key);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PublicKey publicKey = keyFactory.generatePublic(keySpec);
            return publicKey;
        }
     
        //获取私钥
        public static PrivateKey getPrivateKey(String key) throws Exception {
            byte[] keyBytes;
            keyBytes = (new BASE64Decoder()).decodeBuffer(key);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            return privateKey;
        }
     
        //解码返回byte
        public static byte[] decryptBASE64(String key) throws Exception {
            return (new BASE64Decoder()).decodeBuffer(key);
        }
     
        //编码返回字符串
        public static String encryptBASE64(byte[] key) throws Exception {
            return (new BASE64Encoder()).encodeBuffer(key);
        }
     
        //***************************签名和验证*******************************  
        public static String sign(byte[] data, String privateKeyStr) throws Exception {
            PrivateKey priK = getPrivateKey(new String(hexToBytes(privateKeyStr)));
            Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
            sig.initSign(priK);
            sig.update(data);
            return bytesToHex(sig.sign());
        }
     
        public static boolean verify(byte[] data, String sign, String publicKeyStr) throws Exception {
            PublicKey pubK = getPublicKey(new String(hexToBytes(publicKeyStr)));
            Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
            sig.initVerify(pubK);
            sig.update(data);
            return sig.verify(hexToBytes(sign));
        }
     
        //************************加密解密**************************  
        public static String encrypt(byte[] plainText, String publicKeyStr) throws Exception {
            PublicKey publicKey = getPublicKey(new String(hexToBytes(publicKeyStr)));
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            int inputLen = plainText.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            int i = 0;
            byte[] cache;
            while(inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK){
                    cache = cipher.doFinal(plainText, offSet, MAX_ENCRYPT_BLOCK);
                } else{
                    cache = cipher.doFinal(plainText, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptText = out.toByteArray();
            out.close();
            return bytesToHex(encryptText);
        }
     
        public static String decrypt(String encryptTextHex, String privateKeyStr) throws Exception {
            byte[] encryptText = hexToBytes(encryptTextHex);
            PrivateKey privateKey = getPrivateKey(new String(hexToBytes(privateKeyStr)));
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            int inputLen = encryptText.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(encryptText, offSet, MAX_DECRYPT_BLOCK);
                } else{
                   cache = cipher.doFinal(encryptText, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] plainText = out.toByteArray();
            out.close();
            return new String(plainText);
        }
     
        public static Map<String, Object> initKey() 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(2);
            keyMap.put(PUBLIC_KEY, publicKey);
            keyMap.put(PRIVATE_KEY, privateKey);
            return keyMap;
        }
     
        /**
         *byte[]转换为16进制字符串
         */
        public static String bytesToHex(byte[] bytes) {
            //一个byte为8位,可用两个十六进制位标识
            char[] buf = new char[bytes.length * 2];
            int a = 0;
            int index = 0;
            for(byte b : bytes) { // 使用除与取余进行转换
                if(b < 0) {
                    a = 256 + b;
                } else {
                    a = b;
                }
     
                buf[index++] = HEX_CHAR[a / 16];
                buf[index++] = HEX_CHAR[a % 16];
            }
            return new String(buf);
        }
        /**
         * 将16进制字符串转换为byte[]
         *
         * @param str
         * @return
         */
        public static byte[] hexToBytes(String str) {
            if(str == null || str.trim().equals("")) {
                return new byte[0];
            }
     
            byte[] bytes = new byte[str.length() / 2];
            for(int i = 0; i < str.length() / 2; i++) {
                String subStr = str.substring(i * 2, i * 2 + 2);
                bytes[i] = (byte) Integer.parseInt(subStr, 16);
            }
     
            return bytes;
        }
        
        public static void main(String[] args) throws Exception {
            Map<String, Object> keyMap;
            String cipherText;
            String input = "10001eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
            try {
                keyMap = initKey();
                String publicKey = RSAUtils.getPublicKeyStr(keyMap);
                System.out.println("公钥------------------");
                System.out.println(publicKey);
                System.out.println("length: " + publicKey.length());
     
                String privateKey = RSAUtils.getPrivateKeyStr(keyMap);
                System.out.println("私钥------------------");
                System.out.println(privateKey);
                System.out.println("length: " + privateKey.length());
     
                System.out.println("测试可行性-------------------");
                System.out.println("明文=======" + input);
                System.out.println("length: " + input.length());
     
                cipherText = RSAUtils.encrypt(input.getBytes(), publicKey);
                //加密后的东西 
                System.out.println("密文=======" + cipherText);
                System.out.println("length: " + cipherText.length());
     
                //开始解密 
                String plainText =RSAUtils. decrypt(cipherText, privateKey);
                System.out.println("解密后明文===== " + new String(plainText));
                System.out.println("验证签名-----------");
     
                String str = "被签名的内容sssssssassssssssssssssssssssssssssssssssss";
                System.out.println("\n原文:" + str);
                String signature = RSAUtils.sign(str.getBytes(), privateKey);
                System.out.println(signature);
                System.out.println(signature.length());
                boolean status = RSAUtils.verify(str.getBytes(), signature, publicKey);
                System.out.println("验证情况:" + status);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
     
    

    AES算法

    AES算法是对称算法,经常与RSA算法结合使用,但因AES算法是对称的,解密相比RSA算法会快一点,效率高一点,因此经常使用RSA算法通过公钥加密key值,使用AES算法加密key+参数,将两个密文通过ajax传到后台,使用RSA算法的私钥解密key值,使用AES算法通过解密后的key来解密参数,根据业务处理参数,将结果通过AES进行加密返回前台,然后通过前端AES解密将结果在前端进行渲染。
    前台使用
    vue引入 npm install crypto-js
    下载地址为:https://gitee.com/gitcrazy/crypto-js/tree/master

    // Plain text encryption  简单使用
    var CryptoJS = require("crypto-js");
    
    // Encrypt
    var ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123').toString();
    
    // Decrypt
    var bytes  = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
    var originalText = bytes.toString(CryptoJS.enc.Utf8);
    
    console.log(originalText); // 'my message'
    // Object encryption
    var CryptoJS = require("crypto-js");
    
    var data = [{id: 1}, {id: 2}]
    
    // Encrypt
    var ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123').toString();
    
    // Decrypt
    var bytes  = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
    var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
    
    console.log(decryptedData); // [{id: 1}, {id: 2}]
    
    //推荐这种方式
    import CryptoJS from 'crypto-js/crypto-js'   
    
    // 默认的 KEY 与 iv 如果没有给
    const KEY = CryptoJS.enc.Utf8.parse('1019E2991V09O17L1019E2991V09O17L')
    const IV = CryptoJS.enc.Utf8.parse('1019E2991V09O17L')
    /**
     * AES加密 :字符串 key iv  返回base64
     */
    export function Encrypt (data, keyStr, ivStr) {
      let key = KEY
      let iv = IV
    
      if (keyStr) {
        key = CryptoJS.enc.Utf8.parse(keyStr)
        iv = CryptoJS.enc.Utf8.parse(ivStr)
      }
    
      let srcs = CryptoJS.enc.Utf8.parse(data)
      var encrypted = CryptoJS.AES.encrypt(srcs, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
      })
      // console.log("-=-=-=-", encrypted.ciphertext)
      return CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
    }
    /**
     * AES 解密 :字符串 key iv  返回base64
     *
     */
    export function Decrypt (encryotData, keyStr, ivStr) {
      let key = KEY
      let iv = IV
    
      if (keyStr) {
        key = CryptoJS.enc.Utf8.parse(keyStr)
        iv = CryptoJS.enc.Utf8.parse(ivStr)
      }
    
      let base64 = CryptoJS.enc.Base64.parse(encryotData)
      let src = CryptoJS.enc.Base64.stringify(base64)
    
      var decrypt = CryptoJS.AES.decrypt(src, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
      })
    
      var decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
      return decryptedStr.toString()
    }
    

    后台使用

    		package com.winning.devops.util;
    		
    		import org.apache.commons.codec.binary.Base64;
    		
    		import javax.crypto.Cipher;
    		import javax.crypto.spec.IvParameterSpec;
    		import javax.crypto.spec.SecretKeySpec;
    		
    		public class AesUtil {
    		
    		    private static String KEY = "1019E2991V09O17L1019E2991V09O17L";
    		
    		    private static String IV = "1019E2991V09O17L";
    		
    		
    		    /**
    		     * 加密方法
    		     *
    		     * @param data 要加密的数据
    		     * @param key  加密key
    		     * @param iv   加密iv
    		     * @return 加密的结果
    		     * @throws Exception
    		     */
    		    public static String encrypt(String data, String key, String iv) throws Exception {
    		        try {
    		            //"算法/模式/补码方式"PKCS5Padding"
    		            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    		            byte[] plaintext = data.getBytes("UTF-8");
    		
    		            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
    		            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
    		
    		            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
    		            byte[] encrypted = cipher.doFinal(plaintext);
    		
    		            return new Base64().encodeToString(encrypted);
    		
    		        } catch (Exception e) {
    		            e.printStackTrace();
    		            return null;
    		        }
    		    }
    		
    		    /**
    		     * 解密方法
    		     *
    		     * @param data 要解密的数据
    		     * @param key  解密key
    		     * @param iv   解密iv
    		     * @return 解密的结果
    		     * @throws Exception
    		     */
    		    public static String decrypt(String data, String key, String iv) throws Exception {
    		        try {
    		            byte[] encrypted1 = new Base64().decode(data);
    		
    		            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    		            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
    		            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
    		
    		            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
    		
    		            byte[] original = cipher.doFinal(encrypted1);
    		            String originalString = new String(original, "UTF-8");
    		            return originalString;
    		        } catch (Exception e) {
    		            e.printStackTrace();
    		            return null;
    		        }
    		    }
    		
    		    /**
    		     * 使用默认的key和iv加密
    		     *
    		     * @param data
    		     * @return
    		     * @throws Exception
    		     */
    		    public static String encrypt(String data) throws Exception {
    		        return encrypt(data, KEY, IV);
    		    }
    		
    		    /**
    		     * 使用默认的key和iv解密
    		     *
    		     * @param data
    		     * @return
    		     * @throws Exception
    		     */
    		    public static String decrypt(String data) throws Exception {
    		        return decrypt(data, KEY, IV);
    		    }
    		
    		
    		    /**
    		     * 测试
    		     */
    		    public static void main(String args[]) throws Exception {
    		
    		        String test1 = "root";
    		        String test = new String(test1.getBytes(), "UTF-8");
    		        String data = null;
    		        String key = KEY;
    		        String iv = IV;
    		        data = encrypt(test, key, iv);
    		        System.out.println("数据:" + test);
    		        System.out.println("加密:" + data);
    		        String jiemi = decrypt(data, key, iv);
    		        System.out.println("解密:" + jiemi);
    		    }
    		
    		}
    

    注意: 后端的补码方式设置为PKCS5Padding,对应vue前端的CryptoJS.pad.Pkcs7。如果此处改为无补码的方式,解密后得到的字符串会有多余空格。

    展开全文
  • JAVA HMAC SHA256位加密算法

    千次阅读 2021-03-19 20:27:42
    import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; public class HMAC { ... String s=HMACSHA256("123","21+20t4jm4DlkMv3nA5OSf76GrH+ifEORkO3T2yztec="); System.out.print.
  • hash函数思想以及sha256算法

    千次阅读 2020-09-26 20:42:31
    下面介绍sha256函数的实现。 1.信息预处理 分为两个步骤: 1)消息的填充:就是将原始数据M的长度进行扩展,原始数据后面加“1”,接着其余加“0”,直到扩展后的数据M’ mod 512 = 448位为止。 注: 若原始数据...
  • SHA256withRSA java常用的json加签验签工具类 SHA256withRSA 完美工具类 RSAUtils,包含: 1、签名 2、验签 3、公钥加密》私钥解密 4、私钥加密》公钥解密
  • 安全算法SHA-256算法

    千次阅读 2018-07-15 14:39:47
    1. 什么是SHA-256?SHA-256SHA2中的一种。对于长度L(L&...2. SHA-256算法实现步骤2.1 把消息转换为位字符串 SHA-256算法是按照位作为输入,所以进行计算前必须把原始消息(比如字符串、文件等)...
  • PHP实现sha-256哈希算法

    2022-06-04 22:28:21
    哈希 又称作 “散列”,它接收任何一组任意长度...当然除了 sha-256 以外还有一些别的哈希算法,只是目前 sha-256 用的多一些。下面是目前 美国国家标准与技术研究院 发布哈希算法:在编写过程中我主要参考了以下文档和
  • Go语言实现SHA256SHA512哈希算法

    千次阅读 2020-12-15 14:49:39
    问题 编写一个程序,默认情况下打印标准输入的SHA256编码,并支持通过命令行flag定制,输出SHA384或SHA512哈希算法。 代码实现
  • FPGA应用篇【0】比特币SHA256算法实现——原理分析

    千次阅读 热门讨论 2021-02-13 11:54:43
    点开这篇文章的人应该已经都听说过比特币了,如果稍有了解的人就会说比特币挖矿是利用了双哈希算法SHA256。 这里我们不探讨市场行为,不探讨挖矿是否浪费资源,单纯从可行性角度探讨用FPGA挖矿 FPGA番外篇【0】比特...
  • FPGA应用篇【1】比特币SHA256算法实现——核心RTL

    千次阅读 热门讨论 2021-05-02 11:25:04
    FPGA应用篇【1】比特币SHA256算法实现——核心RTL硬件代码哈希核心结果判断状态机串口通信顶层逻辑仿真Testbench编写仿真脚本系统仿真综合编译与测试引脚配置综合编译烧写测试总结 硬件代码 上一篇中主要分析了比特...
  • 加密算法SHA(SHA1、SHA256)

    千次阅读 2021-08-26 15:36:07
    本章讲解典型的加密算法SHA(SHA1、SHA256) 方法 1、概念 安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度...
  • sha256 C语言实现

    千次阅读 2020-11-30 16:13:44
    1. SHA256 对于任意长度的消息,SHA256都会产生一个256bit长的哈希值,称作消息摘要。 这个摘要相当于是个长度为32个字节的数组,通常用一个长度为64的十六进制字符串来表示 ...SHA256算法中的预处理就是在想要Hash
  • MD5和SHA256是非常常用的两种单向散列函数,虽然MD5在2005年已经被中国密码学家王小云攻破,但是曾经也是叱咤风云的,现在比较常用的是SHA256算法,两种算法在go语言中已经被封装好,调用方法相同。 称谓: 单向散列...
  • SHA(Secure Hash Algorithm)被称为安全散列算法,是美国国家安全局(NSA)所设计的,美国国家标准与技术研究院(NIST)发布的一系列密码散列函数,其中包括SHA-1、SHA-224、SHA-256SHA-384和SHA-512等变体。
  • java 数字签名 算法解析(干货)欢迎使用Markdown编辑器数字签名算法概述功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格...
  • 常见签名算法SHA256withRSA

    千次阅读 2022-02-24 14:41:52
    SHA256withRSA 完美工具类 RSAUtils,包含: 1、签名 2、验签 3、公钥加密 4、钥加密私 RSAUtils工具类: import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; ...
  • 加密算法比较:SHA1,SHA256,MD5

    万次阅读 2018-08-07 22:11:58
    MD5输出128bit、SHA1输出160bit、SHA256输出256bit SHA-1是160位的哈希值,而...但是无论是“SHA-2”,“SHA-256”或“SHA-256位”,其实都是指同一种加密算法。但是SHA-224,“SHA-384”或“SHA-512”,表示SHA-...
  • C#自带的类库实现sha265会返回一个byte[] 数组,这个数组的长度是32,js的sha265是64,是把每个byte直接转换成了2个hex字符串。C#中加密后是44位是因为把这个数组用base64编码成了字符串。C#中也直接把byte转换成...
  • 文件加密算法比较:SHA1、SHA256、MD5

    千次阅读 2020-11-20 20:02:00
    MD5算法: MD5是一个安全散列算法,...SHA-1是一种数据加密算法,该算法的思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可以简单的理解为取一串输入码(称为预映射或信息),并把
  • sha1算法

    千次阅读 2021-06-10 19:13:38
    本文章只对sha1算法做简单的介绍和使用方法,不做其他介绍,毕竟对于大多使用者来说会用就足够了 sha1是一种安全哈希算法,也是校验算法,可用于校验文件的完整性。 sha1可处理原始报文长度不能超过2的64次方,然后...
  • SHA-1算法C++实现

    2022-03-10 11:24:16
    主要使用c++将SHA-1算法的加密过程进行了实现。 清晰的算法逻辑结构,详细的注释和测试,清晰易懂。
  • SHA-256算法流程

    2020-04-04 17:37:15
    SHA-256 输入消息:M 输出消息:256位(bit)hash值 步骤: 消息填充:M的长度 mod 512 = R,考虑R(R为输入消息长度按512bit进行分组后,最后一组的长度) R < 448,在最后一组的末尾填充1个“1”及若干个...
  • 随着SSL证书的普及,以“SHA”开头的算法的知名度也越多越高,但并不是很多人能够完全能分清“SHA”所有的算法,本文将会围绕“SHA”展开分析,深入了解SSL证书是如果通过散列算法来完成签名。在细说“SHA”之前,...
  • 【Python应用】SHA256

    万次阅读 2020-04-04 16:33:33
    【Python应用】SHA256
  • sha256算法的硬件系统实现,包括硬件系统设计,VCS仿真,DC综合等流程,及FPGA验证的流程
  • SHA1算法原理过程详解发布日期:2018-12-11SHA1是一种密码散列函数,由美国国家安全局设计,主要适用于数字签名标准里面定义的数字签名算法。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到...
  • c语言实现HmacSHA256算法签名
  • MD5 SHA1 SHA256 SHA512 这4种本质都是摘要函数,不通在于长度 MD5 是 128 位,SHA1 是 160 位 ,SHA256256 位,SHA512 是512 位。 SHA1WithRSA 他的 核心算法是 先用sha1 去摘要,然后使用 RSA 加密。但是 他...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,937
精华内容 3,174
关键字:

sha256算法 位数