数字签名算法rsa

数字签名算法消息传递模型

  1. 由消息发送方构建密钥对,这里由甲方完成。
  2. 由消息发送方公布公钥至消息接收方,这里由甲方将公钥公布给乙方。

RSA

  1. 注意如加密算法区别,这里甲方使用私钥对数据签名,数据与签名形成一则消息发送给乙方,私钥仅用于签名,公钥仅用于验证。

RSA

RSA

RSA数字签名算法源于RSA公钥密码算法的思想,将RSA公钥密码算法按照数字签名的方式运用。RSA数字签名算法是迄今为止应用最为广泛的数字签名算法。 RSA数字签名算法的实现如RSA加密算法一致。RSA数字签名算法主要可分为MD系列和SHA系列。

  1. MD系列主要包括:MD2withRSA和MD5withRSA。
  2. SHA系列主要包括:SHA1withRSA,SHA224withRSA,�SHA256withRSA,SHA384withRSA,SHA512withRSA。

Java 6提供了MD2withRSA,MD5withRSA,SHA1withRSA支持,其他四中SHA算法第三方加密组建包Bouncy Castle提供支持。

 

签名过程:

过程:

1)消息发送者产生一个密钥对(私钥+公钥),然后将公钥发送给消息接收者

2)消息发送者使用消息摘要算法对原文进行加密(加密后的密文称作摘要)

3)消息发送者将上述的摘要使用私钥加密得到密文--这个过程就被称作签名处理,得到的密文就被称作签名(注意,这个签名是名词)

4)消息发送者将原文与密文发给消息接收者

5)消息接收者使用公钥对密文(即签名)进行解密,得到摘要值content1

6)消息接收者使用与消息发送者相同的消息摘要算法对原文进行加密,得到摘要值content2

7)比较content1是不是与content2相等,若相等,则说明消息没有被篡改(消息完整性),也说明消息却是来源于上述的消息发送方(因为其他人是无法伪造签名的,这就完成了“抗否认性”和“认证消息来源”)

 

RSA: 加密原理

RSA-Algorithm

RSA算法演示程序,仅供了解RSA算法实现原理

RSA算法原理

  • 找出两个"很大"的质数:P & Q
  • N = P * Q
  • M = (P - 1) * (Q - 1)
  • 找出整数E,E与M互质,即除了1之外,没有其他公约数
  • 找出整数D,使得E*D除以M余1,即 (E * D) % M = 1

经过上述准备工作之后,可以得到:

  • E是公钥,负责加密
  • D是私钥,负责解密
  • N负责公钥和私钥之间的联系
  • 加密算法,假定对X进行加密
    • (X ^ E) % N = Y
  • 根据费尔马小定义,根据以下公式可以完成解密操作
    • (Y ^ D) % N = X

RSA本身算法的核心思想还是比较简单的,加密、解密算法的区别也只是在乘方取模部分使用的数字有所区别而已

当然,实际运用要比示例代码复杂得多,由于RSA算法的公钥私钥的长度(模长度)要到1024位甚至2048位才能保证安全, 因此,P、Q、E的选取,公钥、私钥的生成,加密、解密模指数运算都有一定的计算程序,需要依托计算机高速运算来完成。

公开密钥的好处

  • 简单 就是一些乘除而已
  • 可靠 可以保证产生的密文是统计独立,并且分布均匀的,也就是说:
    • 不论给出多少份明文和对应的密文,也无法根据已知的明文和密文的对应关系,破译出下一份密文
    • N和E可以公开给任何人加密使用,但是只有掌握密钥D的人才可以解密,即使加密者自己也无法解密
  • 灵活 可以产生很多的公钥E和私钥D的组合给不同的加密者

测试数据说明

P = 11;
Q = 13; N = 143; M = 120; E = 89; D = 209;

提示:本示例程序仅用于演示,N的数值只有143,能够加密的字符范围有限。

 

一个C++实现的算法:

using namespace std;


int Plaintext[100];//明文
long long Ciphertext[100];//密文
int n, e = 0, d;

//二进制转换
int BianaryTransform(int num, int bin_num[])
{

    int i = 0,  mod = 0;

    //转换为二进制,逆向暂存temp[]数组中
    while(num != 0)
    {
        mod = num%2;
        bin_num[i] = mod;
        num = num/2;
        i++;
    }

    //返回二进制数的位数
    return i;
}

//反复平方求幂
long long Modular_Exonentiation(long long a, int b, int n)
{
    int c = 0, bin_num[1000];
    long long d = 1;
    int k = BianaryTransform(b, bin_num)-1;

    for(int i = k; i >= 0; i--)
    {
        c = 2*c;
        d = (d*d)%n;
        if(bin_num[i] == 1)
        {
            c = c + 1;
            d = (d*a)%n;
        }
    }
    return d;
}

//生成1000以内素数
int ProducePrimeNumber(int prime[])
{
    int c = 0, vis[1001];
    memset(vis, 0, sizeof(vis));
    for(int i = 2; i <= 1000; i++)if(!vis[i])
    {
        prime[c++] = i;
        for(int j = i*i; j <= 1000; j+=i)
            vis[j] = 1;
    }

    return c;
}


//欧几里得扩展算法
int Exgcd(int m,int n,int &x)
{
    int x1,y1,x0,y0, y;
    x0=1; y0=0;
    x1=0; y1=1;
    x=0; y=1;
    int r=m%n;
    int q=(m-r)/n;
    while(r)
    {
        x=x0-q*x1; y=y0-q*y1;
        x0=x1; y0=y1;
        x1=x; y1=y;
        m=n; n=r; r=m%n;
        q=(m-r)/n;
    }
    return n;
}

//RSA初始化
void RSA_Initialize()
{
    //取出1000内素数保存在prime[]数组中
    int prime[5000];
    int count_Prime = ProducePrimeNumber(prime);

    //随机取两个素数p,q
    srand((unsigned)time(NULL));
    int ranNum1 = rand()%count_Prime;
    int ranNum2 = rand()%count_Prime;
    int p = prime[ranNum1], q = prime[ranNum2];

    n = p*q;

    int On = (p-1)*(q-1);


    //用欧几里德扩展算法求e,d
    for(int j = 3; j < On; j+=1331)
    {
        int gcd = Exgcd(j, On, d);
        if( gcd == 1 && d > 0)
        {
            e = j;
            break;
        }

    }

}

//RSA加密
void RSA_Encrypt()
{
    cout<<"Public Key (e, n) : e = "<<e<<" n = "<<n<<'\n';
    cout<<"Private Key (d, n) : d = "<<d<<" n = "<<n<<'\n'<<'\n';

    int i = 0;
    for(i = 0; i < 100; i++)
        Ciphertext[i] = Modular_Exonentiation(Plaintext[i], e, n);

    cout<<"Use the public key (e, n) to encrypt:"<<'\n';
    for(i = 0; i < 100; i++)
        cout<<Ciphertext[i]<<" ";
    cout<<'\n'<<'\n';
}

//RSA解密
void RSA_Decrypt()
{
    int i = 0;
    for(i = 0; i < 100; i++)
        Ciphertext[i] = Modular_Exonentiation(Ciphertext[i], d, n);

    cout<<"Use private key (d, n) to decrypt:"<<'\n';
    for(i = 0; i < 100; i++)
        cout<<Ciphertext[i]<<" ";
    cout<<'\n'<<'\n';
}


//算法初始化
void Initialize()
{
    int i;
    srand((unsigned)time(NULL));
    for(i = 0; i < 100; i++)
        Plaintext[i] = rand()%1000;

    cout<<"Generate 100 random numbers:"<<'\n';
    for(i = 0; i < 100; i++)
        cout<<Plaintext[i]<<" ";
    cout<<'\n'<<'\n';
}

int main()
{
    Initialize();

    while(!e)
        RSA_Initialize();

    RSA_Encrypt();

    RSA_Decrypt();

    return 0;
}

  应该是私钥加密,公钥解密的。

Ref:

http://wzhong.logdown.com/posts/234502-rsa-c

https://github.com/liufan321/RSA-Algorithm

 数字签名算法--RSA

https://github.com/LexHsu/Summary/blob/master/02-Algorithm/book/5.1-rsa.md#数字签名算法消息传递模型

posted on 2017-09-15 11:23 桑海 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/sanghai/p/7525450.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RSA是一种非对称加密算法,同时也可以用来进行数字签名。下面是一个使用C语言实现RSA数字签名的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/rsa.h> #include <openssl/evp.h> #include <openssl/pem.h> #define KEY_SIZE 2048 #define SIGN_SIZE 256 int main(int argc, char **argv) { // 读取私钥 FILE *fp = fopen("private_key.pem", "r"); if (fp == NULL) { fprintf(stderr, "Failed to open private key file\n"); exit(1); } RSA *rsa = RSA_new(); rsa = PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL); fclose(fp); // 获取待签名数据 char *data = "Hello world!"; // 计算哈希值 unsigned char hash[EVP_MAX_MD_SIZE]; unsigned int hash_len; EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); EVP_DigestInit(mdctx, EVP_sha256()); EVP_DigestUpdate(mdctx, data, strlen(data)); EVP_DigestFinal(mdctx, hash, &hash_len); EVP_MD_CTX_free(mdctx); // 对哈希值进行签名 unsigned char sign[SIGN_SIZE]; unsigned int sign_len; int ret = RSA_sign(NID_sha256, hash, hash_len, sign, &sign_len, rsa); if (ret != 1) { fprintf(stderr, "Failed to sign data\n"); exit(1); } // 输出签名结果 for (int i = 0; i < sign_len; i++) { printf("%02x", sign[i]); } printf("\n"); RSA_free(rsa); return 0; } ``` 在上面的示例代码中,我们首先读取了一个PEM格式的RSA私钥文件,并使用OpenSSL库提供的函数将其解析为RSA结构体。 接着,我们获取了一个待签名的字符串,并使用OpenSSL库提供的哈希函数计算了该字符串的SHA256哈希值。 最后,我们使用OpenSSL库提供的RSA_sign函数对哈希值进行签名,并将签名结果输出到控制台上。需要注意的是,这里我们使用了SHA256算法作为哈希算法,而签名结果的长度是256字节(2048位)。 当然,这只是一个简单的示例代码,实际使用时还需要考虑其他安全性问题,例如如何保护私钥、如何验证签名等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值