RSA和SHA512实现数字签名(C++)

#include<bits/stdc++.h>

// 循环右移(64位)
#define ROR64( value, bits ) (((value) >> (bits)) | ((value) << (64 - (bits))))

//
//                                                    //
// Ch,:Maj操作                                        //
// S:循环右移    R:同2**128除余右移                    //
// Sigma0:Sigma0函数                                //
// Sigma1:Sigma2函数                                //
// Gamma0:Gamma0函数                                //
// Gamma1:Gamma1函数                                //
//

#define Ch( x, y, z )     (z ^ (x & (y ^ z)))
#define Maj(x, y, z )     (((x | y) & z) | (x & y))
#define S( x, n )         ROR64( x, n )
#define R( x, n )         (((x)&0xFFFFFFFFFFFFFFFFULL)>>((unsigned long long)n))
#define Sigma0( x )       (S(x, 28) ^ S(x, 34) ^ S(x, 39))
#define Sigma1( x )       (S(x, 14) ^ S(x, 18) ^ S(x, 41))
#define Gamma0( x )       (S(x, 1) ^ S(x, 8) ^ R(x, 7))
#define Gamma1( x )       (S(x, 19) ^ S(x, 61) ^ R(x, 6))

#define Sha512Round( a, b, c, d, e, f, g, h, i )       \
     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
     t1 = Sigma0(a) + Maj(a, b, c);                    \
     d += t0;                                          \
     h  = t0 + t1;


using namespace std;
struct KEY
{
	int n;
	int e;
	int d;
	void show()
	{
		cout<<n<<" "<<e<<" "<<d<<endl;
	}
};
struct SHA512_CB
{
    unsigned long long count[2];
    unsigned long long state[8];
    unsigned char buffer[128];
};
class RSA
{
	int p,q,n,e,d;// 
	int fn;//欧拉函数 
	int m,c;//明文,密文 
	int new_m;//新的明文
	int max_pq=300,min_pq=30;//生成的pq范围 
	bool isPrime(int n)//判断是否是素数 ,小素数可以 ,大一点的使用素性判断算法 
	{
		if(n%2==0)
		{
			return false;
		}
		for(int i=3;i<=sqrt(n);i+=2)
		{
			if(n%i==0)
			{
				return false;
			}
		}
		return true;
	}
	int modpow(int n,int m,int mod)//取模指数计算 
	{
		if(m==0)
		{
			return 1;
		}
		if(m==1)
		{
			return n%mod;
		}
		if(m%2==0)
		{
			return modpow((n*n)%mod,m/2,mod);
		}
		else
		{
			return (modpow((n*n)%mod,m/2,mod)*n)%mod;
		}
	}
	void RandomPQ()//随机生成PQ两个互质的数字 
	{
		while(1)
		{
			p = (rand()%(max_pq-min_pq))+min_pq;
			if(isPrime(p))
			{
				break;
			}
		}
		while(1)
		{
			q = (rand()%(max_pq-min_pq))+min_pq;
			if(p!=q&&isPrime(q))
			{
				break;
			}
		} 
		//cout<<"q:"<<q<<endl;
		//cout<<"p:"<<p<<endl;
	}
	void GetN()//根据PQ生成n 
	{
		n=q*p;
		//cout<<"n:"<<n<<endl;
	} 
	void Euler()//计算欧拉函数(n)
	{
		fn = (q-1)*(p-1);
		//cout<<"fn:"<<fn<<endl;
	}
	void GetE()//计算e   满足gcd(欧拉函数(n),e)=1  e< 欧拉函数(n);
	{
		if(!isPrime(fn))
		{
			e=1;
		}
		for(int i=(fn-1);i>=1;i--)
		{
			if(__gcd(fn,i)==1)
			{
				e=i;
				break;
			}
		}
		//cout<<"e:"<<e<<endl;
	}
	//求d  扩展欧几里得  
	int ex_gcd(int a,int b,int &x,int &y)//扩展欧几里得 
	{
	    if(b==0)
	    {
	        x=1;
	        y=0;
	        return a;
	    }
	    int r=ex_gcd(b,a%b,x,y);
	    int t=x;
	    x=y;
	    y=t-a/b*y;
	    return r;
	}
	int mod_reverse(int a,int n)//ax=1(mod n) 求a的逆元x d*e=1mod(m)
	{
	    int flag,x,y;
	    flag=ex_gcd(a,n,x,y);
	    if(flag==1)
	        return (x%n+n)%n;
	    else
	        return -1;
	} 
	void GetD()//计算d,小数字可以,大数字不行 ,稍微大一点的使用扩展欧几里得算法 
	{
		//e*i-1=j*fn;
		/*for(int i=1;i<fn;i++)
		{
			if(e*i%fn==1)
			{
				d=i;
				cout<<"d:"<<d<<endl;
				return ;
			}
		}*/
		d=mod_reverse(e,fn);
		//cout<<"d:"<<d<<endl;
	}
	
	
	void RSA_Main()
	{
		
		RandomPQ();//随机生成PQ两个互质的数字
		GetN();//根据PQ生成n
		Euler();//计算欧拉函数(n)
		GetE();//计算e
		GetD();//计算d
		
	}
	public:
	KEY getKEY()
	{
		RSA_Main();
		KEY key;
		key.n = n;
		key.e = e;
		key.d = d;
		return key;
	}
	vector<int> Encode(int n,int e,string m)//加密 
	{
		vector<int> ans;
		for(int i=0;i<m.size();i++)
		{
			ans.push_back(modpow(m[i],e,n));
		}
		return ans;
	}
	string Decode(int n,int e,vector<int> c)//解密 
	{
		string str="";
		for(int i=0;i<c.size();i++)
		{
			str+=char(modpow(c[i],d,n));
		}
		return str;
	}	
};
class SHA512
{
	// 用于补齐的数,最多补128字节也就是1024bit
	unsigned char PADDING[128] = 
	{
    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	};

// 每次子循环中用到的常量
// 后面加ULL表示long long
	unsigned long long K[80] = 
	{
    0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
    0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
    0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
    0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
    0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
    0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
    0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
    0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
    0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
    0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
    0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
    0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
    0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
    0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
    0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
    0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
    0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
    0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
    0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
    0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
	};
	public :
	void SHA512Init(SHA512_CB *context) 
	{
	    context->count[0] = 0;
	    context->count[1] = 0;
	    context->state[0] = 0x6a09e667f3bcc908ULL;
	    context->state[1] = 0xbb67ae8584caa73bULL;
	    context->state[2] = 0x3c6ef372fe94f82bULL;
	    context->state[3] = 0xa54ff53a5f1d36f1ULL;
	    context->state[4] = 0x510e527fade682d1ULL;
	    context->state[5] = 0x9b05688c2b3e6c1fULL;
	    context->state[6] = 0x1f83d9abfb41bd6bULL;
	    context->state[7] = 0x5be0cd19137e2179ULL;
	}

	void SHA512Update(SHA512_CB *context, unsigned char *input, unsigned long long inputlen) 
	{
	    unsigned long long index = 0, partlen = 0, i = 0; // i记录input的当前位置(初始为0)
	    index = (context->count[1] >> 3) & 0x7F;  //index:总字长除127(11111111)取余后的余数
	    partlen = 128 - index;  //partlen:同128相差的长度
	    context->count[1] += inputlen << 3;  //更新count
	
	    // 统计字符的bit长度,如果小于说明类型溢出了(64bit)无法装下了
	    // 由于最后留下128bit填充字符长度,因而必须引入count[1]保存
	    // 64bit+64bit=128bit
	    if (context->count[1] < (inputlen << 3))
	        context->count[0]++;
	    //右移动61位后就是count[0]应该记录的值。(左移3位,溢出的就是右移动61位的)
	    context->count[0] += inputlen >> 61;
	
	    //
	    //                                                        //
	    //     如果此次更新的长度,大于原长度同128做差的值,    //
	    //     .ie. 加上刚更新的长度满足了128Bytes(1024位)      //
	    //     因而可以进行一次加密循环                            //
	    //                                                        //
	    //
	
	    if (inputlen >= partlen)
	    {
	        //将缺的partlen个字节数据加入缓冲区
	        memcpy(&context->buffer[index], input, partlen);
	        SHA512Transform(context->state, context->buffer);
	
	        // 如果输入的字,还可以进行(还有整128字的)就继续进行一次加密循环
	
	        for (i = partlen; i + 128 <= inputlen; i += 128)
	            SHA512Transform(context->state, &input[i]);
	        // 将当前位置设为0
	        index = 0;
	    }
	    else
	    {
	        i = 0;
	    }
	    // 重新设置buffer区(处理过的字被覆盖成新字)
	    memcpy(&context->buffer[index], &input[i], inputlen - i);
	}
	
	void SHA512Final(SHA512_CB *context, unsigned char digest[64]) 
	{
	    unsigned int index = 0, padlen = 0;
	    unsigned char bits[16]; // 记录字长信息
	    index = (context->count[1] >> 3) & 0x7F; // 字长除127(11111111)取余长度
	    padlen = (index < 112) ? (112 - index) : (240 - index); // 补齐的字长
	    SHA512Encode(bits, context->count, 16);
	    SHA512Update(context, PADDING, padlen);
	    SHA512Update(context, bits, 16);
	    SHA512Encode(digest, context->state, 64);
	}
	
	void SHA512Encode(unsigned char *output, unsigned long long *input, unsigned long long len) 
	{
	    unsigned long long i = 0, j = 0;
	    while (j < len)
	    {
	        output[j+7] = input[i] & 0xFF;
	        output[j + 6] = (input[i] >> 8) & 0xFF; //0xFF:11111111
	        output[j + 5] = (input[i] >> 16) & 0xFF;
	        output[j + 4] = (input[i] >> 24) & 0xFF;
	        output[j + 3] = (input[i] >> 32) & 0xFF;
	        output[j + 2] = (input[i] >> 40) & 0xFF;
	        output[j + 1] = (input[i] >> 48) & 0xFF;
	        output[j] = (input[i] >> 56) & 0xFF;
	        i++;
	        j += 8;
	    }
	}
	
	
	void SHA512Decode(unsigned long long *output, unsigned char *input, unsigned long long len) 
	{
	    unsigned long long i = 0, j = 0;
	    while (j < len)
	    {
	        output[i] = ((unsigned long long)input[j+7]) |
	                    ((unsigned long long)input[j + 6] << 8) |
	                    ((unsigned long long)input[j + 5] << 16) |
	                    ((unsigned long long)input[j + 4] << 24) |
	                    ((unsigned long long)input[j + 3] << 32) |
	                    ((unsigned long long)input[j + 2] << 40) |
	                    ((unsigned long long)input[j + 1] << 48) |
	                    ((unsigned long long)input[j] << 56);
	        i++;
	        j += 8;
	    }
	}
	
	void SHA512Transform(unsigned long long state[8], unsigned char block[128]) 
	{
	    unsigned long long S[8];
	    unsigned long long W[80];
	    unsigned long long t0;
	    unsigned long long t1;
	    int i = 0;
	    /*printf("\n填充后(1024bits):\n0x");
	    for(int index=0;index<128;index++){
	        printf("%02x", block[index]);
	    }
	    printf("\n");*/
	    // 把state的值复制给S
	    for ( i = 0; i < 8; i++ )
	    {
	        S[i] = state[i];
	    }
	
	    // 将字符数组保存的编码转为unsigned long long
	    SHA512Decode(W, block, 128);
	
	    for ( i = 16; i < 80; i++ )//执行80次轮函数 
	    {
	        W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
	    }
	
	    for ( i = 0; i < 80; i += 8 )
	    {
	        Sha512Round(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i + 0);
	        Sha512Round(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], i + 1);
	        Sha512Round(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], i + 2);
	        Sha512Round(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], i + 3);
	        Sha512Round(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], i + 4);
	        Sha512Round(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], i + 5);
	        Sha512Round(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], i + 6);
	        Sha512Round(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], i + 7);
	    }
	    /*printf("\n");
	    printf("A:%I64u\n", S[0]);
	    printf("B:%I64u\n", S[1]);
	    printf("C:%I64u\n", S[2]);
	    printf("D:%I64u\n", S[3]);
	    printf("E:%I64u\n", S[4]);
	    printf("F:%I64u\n", S[5]);
	    printf("G:%I64u\n", S[6]);
	    printf("H:%I64u\n", S[7]);
	    printf("\n");*/
	    // Feedback
	    for ( i = 0; i < 8; i++ )
	    {
	        state[i] = state[i] + S[i];
	    }
	}
	 
}; 
void show_vc(vector<int> & a)
{
	for(int i=0;i<a.size();i++)
	{
		cout<<a[i]; 
	}
	cout<<endl; 
}
string tohex(int a)
{
	string str;
	while(a!=0)
	{
		int val = a%16;
		if(val<=9)
		{
			str=char(val+'0')+str;
		}
		else
		{
			val-=10;
			str=char(val+'a')+str;
		}
		a/=16;
	}
	return str;
} 
int main()
{
	int i;
    unsigned char input[] = "1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz";
    printf("输入字符串的十六进制: 0x");
    for(unsigned int i=0;i<strlen((char*)input);i++){
        printf("%02x", input[i]);
    }
    printf("\n\n");
	
	
	
	SHA512 sha;
	
    unsigned char sha512Code[64];

    SHA512_CB sha512;

    sha.SHA512Init(&sha512);
    sha.SHA512Update(&sha512, input, strlen((char *)input));
    sha.SHA512Final(&sha512, sha512Code);

    //Md5加密后的32位结果
    printf("\n加密前:%s\n加密后128位:", input);
    for (i = 0; i < 64; i++)
    {
        printf("%02", sha512Code[i]);
		//cout<<(int)sha512Code[i]<<" "<<tohex((int)sha512Code[i])<<endl;
		
    }
    printf("\n");
	string m;
	for(int i=0;i<64;i++)
	{
		m+=tohex((int)sha512Code[i]);
	}
	RSA rsa;
	KEY key = rsa.getKEY();
	cout<<"生成的n,e,d:"; 
	key.show();
	cout<<endl;
	cout<<"原文:"<<m<<endl<<endl;
	string ans;
	vector<int> c;
	c=rsa.Encode(key.n,key.e,m);
	cout<<"密文:";
	show_vc(c);
	cout<<endl;
	ans=rsa.Decode(key.n,key.d,c);
	cout<<"解密之后的原文:"<<ans<<endl<<endl;
	
    getchar();

    return 0;
}
以下是一个基于 OpenSSL 库的 RSA 数字签名实现的示例代码: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/rsa.h> #include <openssl/pem.h> int main(int argc, char *argv[]) { if (argc != 4) { printf("Usage: %s <private_key_file> <input_file> <signature_file>\n", argv[0]); return 1; } const char *privkey_path = argv[1]; const char *input_path = argv[2]; const char *sig_path = argv[3]; // 读取私钥文件 FILE *privkey_file = fopen(privkey_path, "r"); if (!privkey_file) { perror("Failed to open private key file"); return 1; } RSA *rsa = PEM_read_RSAPrivateKey(privkey_file, NULL, NULL, NULL); fclose(privkey_file); if (!rsa) { fprintf(stderr, "Failed to read private key file\n"); return 1; } // 读取输入文件 FILE *input_file = fopen(input_path, "rb"); if (!input_file) { perror("Failed to open input file"); return 1; } fseek(input_file, 0, SEEK_END); long input_size = ftell(input_file); fseek(input_file, 0, SEEK_SET); char *input_data = malloc(input_size); fread(input_data, input_size, 1, input_file); fclose(input_file); // 计算输入文件的哈希值 unsigned char hash[SHA256_DIGEST_LENGTH]; SHA256((const unsigned char *)input_data, input_size, hash); // 签名哈希值 unsigned int sig_len; unsigned char *sig_data = malloc(RSA_size(rsa)); if (!RSA_sign(NID_sha256, hash, sizeof(hash), sig_data, &sig_len, rsa)) { fprintf(stderr, "Failed to sign hash\n"); return 1; } // 写入签名文件 FILE *sig_file = fopen(sig_path, "wb"); if (!sig_file) { perror("Failed to open signature file"); return 1; } fwrite(sig_data, sig_len, 1, sig_file); fclose(sig_file); printf("Signature generated successfully.\n"); RSA_free(rsa); free(input_data); free(sig_data); return 0; } 在此示例中,我们使用 OpenSSL 库计算 SHA256 哈希值,然后使用 RSA 签名哈希值。请注意,在实际应用中,您可能需要使用更安全的哈希算法和更复杂的签名方案。另外,请确保您的私钥文件在存储和传输时得到适当的保护。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值