实现SM4-ECB、CBC、CFB、OFB算法(大数据版)
2022/9/14 14:16:20
本文主要是介绍实现SM4-ECB、CBC、CFB、OFB算法(大数据版),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
base_sm4类参考:
实现SM4算法(16字节版)
sm4.h
#pragma once #include <algorithm> #include <iostream> #include "D:\C++\实现SM4算法(16字节版)\base_sm4.h" constexpr bool SM4_ENCRYPT = 1; //进行加密运算 constexpr bool SM4_DECRYPT = 0; //进行解密运算 constexpr unsigned SM4_BLOCK_SIZE = 16; //每个分组的大小为16字节,32位 class sm4 : public base_sm4 { public: /* ECB模式的SM4算法 ECB模式是最早采用的简单模式,它将加密的数据分成若干组,每组的大小跟加密密钥长度相同,然后每组都用相同的密钥进行加密。相同的明文会产生相同的密文。 每个分组的运算(加密或解密)都是独立的,每个分组加密只需要密钥和明文分组即可,每个分组解密也只需要密钥和密文分组即可。 in:明文或者密文 out:存储明文或者密文,要求out有足够的空间,且长度不低于in的长度 lenght:in的长度 key:16字节长度的秘钥 type:指定为加密或者解密 */ void sm4Ecb(std::vector<unsigned char>& in, std::vector<unsigned char>& out, const size_t lenght, std::vector<unsigned char>& key, const bool type); /* CBC模式的SM4算法 初始向量(或称初向量)是一个固定长度的比特串。一般使用时会要求它是随机数或伪随机数。使用随机数产生的初始向量,使得同一个密钥加密的结果每次都不同,这样攻击者难以对同一把密钥的密文进行破解。 加密时,第一个明文块和初始向量进行异或后,再用key进行加密,以后每个明文块与前一个分组结果(密文)块进行异或后,再用key进行加密。 解密时,第一个密文块先用key解密,得到的中间结果再与初始向量进行异或后得到第一个明文分组(第一个分组的最终明文结果),后面每个密文块也是先用key解密,得到的中间结果再与前一个密文分组(注意是解密之前的密文分组)进行异或后得到本次明文分组。 in:明文或者密文 out:存储明文或者密文,要求out有足够的空间,且长度不低于in的长度 lenght:in的长度 key:16字节长度的秘钥 ivec:初始向量,16字节 type:指定为加密或者解密 */ void sm4Cbc(std::vector<unsigned char>& in, std::vector<unsigned char>& out, const size_t lenght, std::vector<unsigned char>& key, std::vector<unsigned char>&ivec, const bool type); /* CFB模式的SM4算法 也需要初始向量。 加密第一个分组时,先对初始向量进行加密,得到的中间结果再与第一个明文分组进行异或得到第一个密文分组;加密后面的分组时,把前一个密文分组作为向量先加密,得到的中间结果再与当前明文分组进行异或得到密文分组。 解密第一个分组时,先对初始向量进行加密运算(注意,用的是加密算法),得到的中间结果再与第一个密文分组进行异或得到明文分组;解密后面的分组时,把上一个密文分组当作向量进行加密运算(注意,用的还是加密算法),得到的中间结果再与本次的密文分组进行异或得到本次的明文分组。 in:明文或者密文 out:存储明文或者密文,要求out有足够的空间,且长度不低于in的长度 lenght:in的长度 key:16字节长度的秘钥 ivec:初始向量,16字节 type:指定为加密或者解密 */ void sm4Cfb(std::vector<unsigned char>& in, std::vector<unsigned char>& out, const size_t lenght, std::vector<unsigned char>& key, std::vector<unsigned char>& ivec, const bool type); /* OFB模式的SM4算法 也需要初始向量。 加密第一个分组时,先对初始向量进行加密,得到的中间结果再与第一个明文分组进行异或得到第一个密文分组;加密后面的分组时,把前一个中间结果(前一个分组的向量的密文)作为向量先加密,得到的中间结果再与当前明文分组进行异或得到密文分组。 解密第一个分组时,先对初始向量进行加密运算(注意用的是加密算法),得到的中间结果再与第一个密文分组进行异或得到明文分组;解密后面的分组时,把上一个中间结果(前一个分组的向量的密文,因为用的依然是加密算法)当作向量进行加密运算(注意用的是加密算法),得到的中间结果再与本次的密文分组进行异或得到本次的明文分组。 in:明文或者密文 out:存储明文或者密文,要求out有足够的空间,且长度不低于in的长度 lenght:in的长度 key:16字节长度的秘钥 ivec:初始向量,16字节 */ void sm4Ofb(std::vector<unsigned char>& in, std::vector<unsigned char>& out, const size_t lenght, std::vector<unsigned char>& key, std::vector<unsigned char>& ivec); //ecb加解密检查 int sm4ecbcheck(); //cbc加解密检查 int sm4cbccheck(); //cfb加解密检查 int sm4cfbcheck(); //ofb加解密检查 int sm4ofbcheck(); };View Code
sm4.cpp
#include "sm4.h" void sm4::sm4Ecb(std::vector<unsigned char> &in, std::vector<unsigned char> &out, const size_t lenght, std::vector<unsigned char> &key, const bool type){ size_t len = lenght; //判断参数是否为空,以及判断长度是否为16的倍数 if (in.size() == 0 || out.size() == 0 || key.size() == 0 || lenght % SM4_BLOCK_SIZE != 0) { return; } std::vector<unsigned char>::iterator in_iterator = in.begin(); std::vector<unsigned char>::iterator out_iterator = out.begin(); while (len >= SM4_BLOCK_SIZE) { //SM4加解密的分组大小为128Bit,故对消息进行加解密时,若消息长度过长,则需要进行循环分组加解密。 if (type== SM4_ENCRYPT) { //加密 this->SM4_Encrypt(key.begin(), in_iterator, out_iterator); } else { this->SM4_Decrypt(key.begin(), in_iterator, out_iterator); } len -= SM4_BLOCK_SIZE; //没处理完一个分组,长度就要减去16 in_iterator += SM4_BLOCK_SIZE; //原文数据迭代器偏移16字节,即16个char,指向新的未处理的数据 out_iterator += SM4_BLOCK_SIZE; //结果迭代器也要偏移16字节,即16个char,指向新的未占用的空间 } } void sm4::sm4Cbc(std::vector<unsigned char>& in, std::vector<unsigned char>& out, const size_t lenght, std::vector<unsigned char>& key, std::vector<unsigned char>& ivec, const bool type) { /* * 这个算法支持in和out指向同一个缓冲区(称为原地加解密),根据CBC模式的原理,加密时不必区分in和out是否相同,而解密时需要区分。 */ size_t len = lenght; std::vector<unsigned char> temp(SM4_BLOCK_SIZE, 0); std::vector<unsigned char>::iterator iv_iterator = ivec.begin(); std::vector<unsigned char> iv_temp(SM4_BLOCK_SIZE, 0); //判断参数是否为空,以及判断长度是否为16的倍数 if (in.size() == 0 || out.size() == 0 || key.size() == 0 || ivec.size() == 0 || lenght % SM4_BLOCK_SIZE != 0) { return; } if (type == SM4_ENCRYPT) { //加密 std::vector<unsigned char>::iterator in_iterator = in.begin(); std::vector<unsigned char>::iterator out_iterator = out.begin(); while (len >= SM4_BLOCK_SIZE) { /* * 加密时,第一个明文块和初始向量iv进行异或后,再用key进行加密; * 以后每个明文块与前一个分组结果(密文)块进行异或后,再用key进行加密 * 前一个分组结果(密文)块当做本次iv */ for (int i{}; i < SM4_BLOCK_SIZE; ++i) { out_iterator[i] = in_iterator[i] ^ iv_iterator[i]; } //用key进行加密 this->SM4_Encrypt(key.begin(), out_iterator, out_iterator); iv_iterator = out_iterator; //保存当前结果,以便下一次循环中和明文进行异或运算 len -= SM4_BLOCK_SIZE; //减去已完成的字节数 in_iterator += SM4_BLOCK_SIZE; //偏移明文数据的迭代器,指向未加密的数据开头 out_iterator += SM4_BLOCK_SIZE; //偏移密文数据的迭代器,指向未放置数据的内存 } } else { //解密 std::vector<unsigned char>::iterator in_iterator = in.begin(); std::vector<unsigned char>::iterator out_iterator = out.begin(); //不同的vector的迭代器不能相互比较,哪怕vector的类型、大小等一样,只要迭代器的来源不属于同一个vector,那么就不能比较。 //if (in_iterator != out_iterator) { if (in.data() != out.data()) { //in和out属于不同的缓冲区 while (len >= SM4_BLOCK_SIZE) { //循环分组处理 this->SM4_Decrypt(key.begin(), in_iterator, out_iterator); for (int i{}; i < SM4_BLOCK_SIZE; ++i) { out_iterator[i] = out_iterator[i] ^ iv_iterator[i]; } iv_iterator = in_iterator; len -= SM4_BLOCK_SIZE; //减去已完成的字节数 in_iterator+= SM4_BLOCK_SIZE; //偏移密文数据迭代器,指向还没解密的数据开头 out_iterator += SM4_BLOCK_SIZE;; //偏移结果数据指针,指向未放置数据的内存 } } else { //in和out属于相同的缓冲区 iv_temp.insert(iv_temp.end(), ivec.begin(), ivec.begin() + SM4_BLOCK_SIZE); while (len >= SM4_BLOCK_SIZE) { //暂存本次分组密文,因为in要存放结果明文 temp.insert(temp.end(), in.begin(), in.begin() + SM4_BLOCK_SIZE); this->SM4_Encrypt(key.begin(), in_iterator, out_iterator); for (int i{}; i < SM4_BLOCK_SIZE; ++i) { out_iterator[i] = out_iterator[i] ^ iv_temp[i]; } iv_temp.clear(); iv_temp.insert(iv_temp.end(), temp.begin(), temp.begin() + SM4_BLOCK_SIZE); len -= SM4_BLOCK_SIZE; //减去已完成的字节数 in_iterator += SM4_BLOCK_SIZE; //偏移密文数据迭代器,指向还没解密的数据开头 out_iterator += SM4_BLOCK_SIZE;; //偏移结果数据指针,指向未放置数据的内存 } } } } void sm4::sm4Cfb(std::vector<unsigned char>& in, std::vector<unsigned char>& out, const size_t lenght, std::vector<unsigned char>& key, std::vector<unsigned char>& ivec, const bool type) { //CFB模式和CBC类似,也需要IV rsize_t len = lenght; unsigned char ch{}; std::vector<unsigned char> iv; //判断参数是否为空,以及判断长度是否为16的倍数 if (in.size() == 0 || out.size() == 0 || key.size() == 0 || ivec.size() == 0 || lenght % SM4_BLOCK_SIZE != 0) { return; } iv.insert(iv.begin(), ivec.begin(), ivec.begin() + SM4_BLOCK_SIZE); std::vector<unsigned char>::iterator in_iterator = in.begin(); std::vector<unsigned char>::iterator out_iterator = out.begin(); if (type == SM4_ENCRYPT) { //加密 std::vector<unsigned char>::iterator iv_iterator = iv.begin(); int i{}; while (len--) { if (!i) { //第一次循环才进入这里 this->SM4_Encrypt(key.begin(), iv_iterator, iv_iterator); } iv[i] = *(out_iterator++) = *(in_iterator++) ^ iv[i]; i = (i + 1) % SM4_BLOCK_SIZE; //上面两行代码就很精妙,实现了iv始终在0~SM4_BLOCK_SIZE之间 } } else { //解密 //解密也是使用的SM4_Encrypt std::vector<unsigned char>::iterator iv_iterator = iv.begin(); int i{}; while (len--) { if (!i) { this->SM4_Encrypt(key.begin(), iv_iterator, iv_iterator); } ch = *in_iterator; *(out_iterator++) = *(in_iterator++) ^ iv[i]; //上面这句代码应该可以换成*(++out_iterator) = *(++in_iterator) ^ iv[i]; iv[i]=ch; i = (i + 1) % SM4_BLOCK_SIZE; //上面两行代码就很精妙,实现了iv始终在0~SM4_BLOCK_SIZE之间 } } } void sm4::sm4Ofb(std::vector<unsigned char>& in, std::vector<unsigned char>& out, const size_t lenght, std::vector<unsigned char>& key, std::vector<unsigned char>& ivec) { size_t len = lenght; std::vector<unsigned char> iv; //判断参数是否为空,以及判断长度是否为16的倍数 if (in.size() == 0 || out.size() == 0 || key.size() == 0 || ivec.size() == 0 || lenght % SM4_BLOCK_SIZE != 0) { return; } iv.insert(iv.begin(), ivec.begin(), ivec.begin() + SM4_BLOCK_SIZE); std::vector<unsigned char>::iterator in_iterator = in.begin(); std::vector<unsigned char>::iterator out_iterator = out.begin(); std::vector<unsigned char>::iterator iv_iterator = iv.begin(); //OFB模式的加密和解密是一致的 int i{}; while (--len) { if (!i) { this->SM4_Encrypt(key.begin(), iv_iterator, iv_iterator); } *(++out_iterator) = *(++in_iterator) ^ iv[i]; i = (i + 1) % SM4_BLOCK_SIZE; } } int sm4::sm4ecbcheck(){ int i, len, ret = 0; std::vector<unsigned char> key{ 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 }; std::vector<unsigned char> plain{ 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 }; std::vector<unsigned char> cipher{ 0x68,0x1e,0xdf,0x34,0xd2,0x06,0x96,0x5e,0x86,0xb3,0xe9,0x4f,0x53,0x6e,0x42,0x46 }; std::vector<unsigned char> En_output; std::vector<unsigned char> De_output; std::vector<unsigned char> in; std::vector<unsigned char> out; std::vector<unsigned char> chk; En_output.resize(16); //需要提前准备好充足的空间 this->sm4Ecb(plain, En_output, 16, key, SM4_ENCRYPT); //比较两个缓冲区的值是否一致 if (std::equal(cipher.begin(), cipher.end(), En_output.begin())) { std::cout << "ecb enc(len=16) memcmp ok\n"; } else { std::cout << "ecb enc(len=16) memcmp failed\n"; std::cout << "En_output:\n"; std::copy(En_output.begin(), En_output.end(), std::ostream_iterator<unsigned>(std::cout, ",")); std::cout << "cipher:\n"; std::copy(cipher.begin(), cipher.end(), std::ostream_iterator<unsigned>(std::cout, ",")); std::cout << "\n"; } ////比较两个缓冲区的值是否一致 //if (memcmp(En_output.data(), cipher.data(), cipher.size())) { // puts("ecb enc(len=16) memcmp failed"); //} //else puts("ecb enc(len=16) memcmp ok"); De_output.resize(SM4_BLOCK_SIZE); ////需要提前准备好充足的空间 this->sm4Ecb(cipher, De_output, SM4_BLOCK_SIZE, key, SM4_DECRYPT); //比较两个缓冲区的值是否一致 if (std::equal(plain.begin(), plain.end(), De_output.begin())) { std::cout << "ecb dec(len=16) memcmp ok\n"; } else { std::cout << "ecb dec(len=16) memcmp failed\n"; std::cout << "En_output:\n"; std::copy(De_output.begin(), De_output.end(), std::ostream_iterator<unsigned>(std::cout, ",")); std::cout << "cipher:\n"; std::copy(cipher.begin(), cipher.end(), std::ostream_iterator<unsigned>(std::cout, ",")); std::cout << "\n"; } //if (memcmp(De_output.data(), plain.data(), SM4_BLOCK_SIZE)) puts("ecb dec(len=16) memcmp failed"); //else puts("ecb dec(len=16) memcmp ok"); len = 32; for (i = 0; i < 8; i++) { //memset(in, i, len); in.insert(in.end(), len, i); out.resize(in.size()); //这里是默认了为16的倍数 this->sm4Ecb(in, out, len, key, SM4_ENCRYPT); //加密 chk.resize(in.size()); //这里是默认了为16的倍数 this->sm4Ecb(out, chk, len, key, SM4_DECRYPT); //解密 if (std::equal(in.begin(), in.end(), chk.begin())) { std::cout << "ecb enc(len=" << len << ") memcmp ok\n"; } else { std::cout << "ecb enc(len=" << len << ") memcmp failed\n"; } //if (memcmp(in.data(), chk.data(), len)) printf("ecb enc/dec(len=%d) memcmp failed\n", len); //else printf("ecb enc/dec(len=%d) memcmp ok\n", len); len = 2 * len; in.clear(); } return 0; } int sm4::sm4cbccheck() { int i, len, ret = 0; std::vector<unsigned char> key { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };//密钥 std::vector<unsigned char> iv { 0xeb,0xee,0xc5,0x68,0x58,0xe6,0x04,0xd8,0x32,0x7b,0x9b,0x3c,0x10,0xc9,0x0c,0xa7 }; //初始化向量 std::vector<unsigned char> plain { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,0x29,0xbe,0xe1,0xd6,0x52,0x49,0xf1,0xe9,0xb3,0xdb,0x87,0x3e,0x24,0x0d,0x06,0x47 }; //明文 std::vector<unsigned char> cipher { 0x3f,0x1e,0x73,0xc3,0xdf,0xd5,0xa1,0x32,0x88,0x2f,0xe6,0x9d,0x99,0x6c,0xde,0x93,0x54,0x99,0x09,0x5d,0xde,0x68,0x99,0x5b,0x4d,0x70,0xf2,0x30,0x9f,0x2e,0xf1,0xb7 }; //密文 std::vector<unsigned char> En_output; std::vector<unsigned char> De_output; std::vector<unsigned char> in; std::vector<unsigned char> out; std::vector<unsigned char> chk; En_output.resize(plain.size()); //sizeof是输出的字节数,对于这里其实就是长度 this->sm4Cbc(plain, En_output, plain.size(), key, iv, SM4_ENCRYPT); //加密 //比较是否相等 if (std::equal(cipher.begin(), cipher.end(), En_output.begin())) { std::cout << "cbc enc(len=16) memcmp ok\n"; } else { std::cout << "cbc enc(len=16) memcmp failed\n"; std::cout << "En_output:\n"; std::copy(En_output.begin(), En_output.end(), std::ostream_iterator<unsigned>(std::cout, ",")); std::cout << "cipher:\n"; std::copy(cipher.begin(), cipher.end(), std::ostream_iterator<unsigned>(std::cout, ",")); std::cout << "\n"; } //if (memcmp(En_output, cipher, 16)) puts("cbc enc(len=32) memcmp failed"); //else puts("cbc enc(len=32) memcmp ok"); De_output.resize(cipher.size()); this->sm4Cbc(cipher, De_output, cipher.size(), key, iv, SM4_DECRYPT); //比较是否相等 if (std::equal(plain.begin(), plain.end(), De_output.begin())) { std::cout << "cbc dec(len=16) memcmp ok\n"; } else { std::cout << "cbc dec(len=16) memcmp failed\n"; std::cout << "En_output:\n"; std::copy(De_output.begin(), De_output.end(), std::ostream_iterator<unsigned>(std::cout, ",")); std::cout << "cipher:\n"; std::copy(plain.begin(), plain.end(), std::ostream_iterator<unsigned>(std::cout, ",")); std::cout << "\n"; } /*if (memcmp(De_output, plain, SM4_BLOCK_SIZE)) puts("cbc dec(len=32) memcmp failed"); else puts("cbc dec(len=32) memcmp ok");*/ len = 32; for (i = 0; i < 8; i++) { //memset(in, i, len); in.resize(len, i); out.resize(len); this->sm4Cbc(in, out, len, key, iv, SM4_ENCRYPT); chk.resize(len); this->sm4Cbc(out, chk, len, key, iv, SM4_DECRYPT); //比较是否相等 if (std::equal(in.begin(), in.end(), chk.begin())) { std::cout << "cbc enc/dec(len=" << len << ") memcmp ok\n"; } else { std::cout << "cbc enc/dec(len=" << len << ") memcmp failed\n"; std::cout << "En_output:\n"; std::copy(in.begin(), in.end(), std::ostream_iterator<unsigned>(std::cout, ",")); std::cout << "cipher:\n"; std::copy(chk.begin(), chk.end(), std::ostream_iterator<unsigned>(std::cout, ",")); } //if (memcmp(in, chk, len)) printf("cbc enc/dec(len=%d) memcmp failed\n", len); //else printf("cbc enc/dec(len=%d) memcmp ok\n", len); len = 2 * len; } return 0; } int sm4::sm4cfbcheck() { int i, len, ret = 0; std::vector<unsigned char> key{ 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };//密钥 std::vector<unsigned char> iv{ 0xeb,0xee,0xc5,0x68,0x58,0xe6,0x04,0xd8,0x32,0x7b,0x9b,0x3c,0x10,0xc9,0x0c,0xa7 }; //初始化向量 std::vector<unsigned char> in; std::vector<unsigned char> out; std::vector<unsigned char> chk; len = 16; for (i = 0; i < 9; i++) { in.resize(len, i); out.resize(len); chk.resize(len); this->sm4Cfb(in, out, len, key, iv, SM4_ENCRYPT); this->sm4Cfb(out, chk, len, key, iv, SM4_DECRYPT); //比较是否相等 if (std::equal(in.begin(), in.end(), chk.begin())) { std::cout << "cfb enc/dec(len=" << len << ") memcmp ok\n"; } else { std::cout << "\ncfb enc/dec(len=" << len << ") memcmp failed"; std::cout << "\nin:"; std::copy(in.begin(), in.end(), std::ostream_iterator<unsigned>(std::cout, ",")); std::cout << "\nout:"; std::copy(out.begin(), out.end(), std::ostream_iterator<unsigned>(std::cout, ",")); std::cout << "\nchk:"; std::copy(chk.begin(), chk.end(), std::ostream_iterator<unsigned>(std::cout, ",")); break; } /*if (memcmp(in, chk, len)) printf("cfb enc/dec(len=%d) memcmp failed\n", len); else printf("cfb enc/dec(len=%d) memcmp ok\n", len);*/ len = 2 * len; } return 0; } int sm4::sm4ofbcheck() { int i, len, ret = 0; std::vector<unsigned char> key{ 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };//密钥 std::vector<unsigned char> iv{ 0xeb,0xee,0xc5,0x68,0x58,0xe6,0x04,0xd8,0x32,0x7b,0x9b,0x3c,0x10,0xc9,0x0c,0xa7 }; //初始化向量 std::vector<unsigned char> in; std::vector<unsigned char> out; std::vector<unsigned char> chk; len = 16; for (i = 0; i < 9; i++) { out.resize(len); chk.resize(len); in.resize(len, i); this->sm4Ofb(in, out, len, key, iv); this->sm4Ofb(out, chk, len, key, iv); //比较是否相等 if (std::equal(in.begin(), in.end(), chk.begin())) { std::cout << "ofb enc/dec(len=" << len << ") memcmp ok\n"; } else { std::cout << "\nofb enc/dec(len=" << len << ") memcmp failed"; std::cout << "\nin:"; std::copy(in.begin(), in.end(), std::ostream_iterator<unsigned>(std::cout, ",")); std::cout << "\nout:"; std::copy(out.begin(), out.end(), std::ostream_iterator<unsigned>(std::cout, ",")); std::cout << "\nchk:"; std::copy(chk.begin(), chk.end(), std::ostream_iterator<unsigned>(std::cout, ",")); break; } /*if (memcmp(in, chk, len)) printf("ofb enc/dec(len=%d) memcmp failed\n", len); else printf("ofb enc/dec(len=%d) memcmp ok\n", len);*/ len = 2 * len; } return 0; }View Code
实现SM4-ECB、CBC、CFB、OFB算法(大数据版).cpp
// 实现SM4-ECB、CBC、CFB、OFB算法(大数据版).cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <iostream> #include "sm4.h" int main() { sm4 s; s.sm4ofbcheck(); } // 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 // 调试程序: F5 或调试 >“开始调试”菜单 // 入门使用技巧: // 1. 使用解决方案资源管理器窗口添加/管理文件 // 2. 使用团队资源管理器窗口连接到源代码管理 // 3. 使用输出窗口查看生成输出和其他消息 // 4. 使用错误列表窗口查看错误 // 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 // 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件View Code
这篇关于实现SM4-ECB、CBC、CFB、OFB算法(大数据版)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享
- 2024-11-22ansible 的archive 参数是什么意思?-icode9专业技术文章分享
- 2024-11-22ansible 中怎么只用archive 排除某个目录?-icode9专业技术文章分享
- 2024-11-22exclude_path参数是什么作用?-icode9专业技术文章分享
- 2024-11-22微信开放平台第三方平台什么时候调用数据预拉取和数据周期性更新接口?-icode9专业技术文章分享
- 2024-11-22uniapp 实现聊天消息会话的列表功能怎么实现?-icode9专业技术文章分享
- 2024-11-22在Mac系统上将图片中的文字提取出来有哪些方法?-icode9专业技术文章分享
- 2024-11-22excel 表格中怎么固定一行显示不滚动?-icode9专业技术文章分享
- 2024-11-22怎么将 -rwxr-xr-x 修改为 drwxr-xr-x?-icode9专业技术文章分享
- 2024-11-22在Excel中怎么将小数向上取整到最接近的整数?-icode9专业技术文章分享