教学服务系统

 找回密码
 立即注册
搜索
查看: 500|回复: 3

信息计算2019级28号徐源璞

[复制链接]

10

主题

16

帖子

78

积分

注册会员

Rank: 2

积分
78
发表于 2022-6-2 12:33:23 | 显示全部楼层 |阅读模式
RSA加密及签名的实现
一、加解密过程简述
A和B进行通信加密,B要先生成一对RSA密钥,B自己持有私钥,给A公钥 —>A使用B的公钥加密要发送的内容,然后B接收到密文后通过自己的私钥解密内容。
二、签名验签过程简述
A给B发送消息,A先计算出消息的消息摘要,然后使用自己的私钥加密消息摘要,被加密的消息摘要就是签名.(A用自己的私钥给消息摘要加密成为签名)。
B收到消息后,也会使用和A相同的方法提取消息摘要,然后用A的公钥解密签名,并与自己计算出来的消息摘要进行比较–>如果相同则说明消息是A发送给B的,同时,A也无法否认自己发送消息给B的事实.(B使用A的公钥解密签名文件的过程,叫做"验签")。
三、签名和验签过程详细理解
签名过程:
(1). A计算消息m的消息摘要,记为 h(m)
(2). A使用私钥(n,d)对h(m)加密,生成签名s, s满足:s=(h(m))^d mod n;
   由于A是用自己的私钥对消息摘要加密,所以只用使用s的公钥才能解密该消息摘要,这样A就不可否认自己发送了该消息给B
(3). A发送消息和签名(m,s)给B
验签过程:
(1). B计算消息m的消息摘要(计算方式和A相同),记为h(m)
(2). B使用A的公钥(n,e)解密s,得到 H(m), H(m) = s^e mod n
(3). B比较H(m)与h(m),相同才能证明验签成功



回复

使用道具 举报

10

主题

16

帖子

78

积分

注册会员

Rank: 2

积分
78
 楼主| 发表于 2022-6-2 12:33:43 | 显示全部楼层
四、代码部分

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.InputStream;

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.interfaces.RSAPrivateKey;

import java.security.interfaces.RSAPublicKey;

import java.security.spec.PKCS8EncodedKeySpec;

import java.security.spec.X509EncodedKeySpec;

import java.util.Base64;

import javax.crypto.Cipher;



public class RSAUtil{



public static final String SIGN_ALGORITHMS = "SHA1WithRSA";



/**加密算法RSA*/

public static final String KEY_ALGORITHM = "RSA";



/**RSA最大加密明文大小*/

private static final int MAX_ENCRYPT_BLOCK = 117;



/**RSA最大解密密文大小*/

private static final int MAX_DECRYPT_BLOCK = 128;



/**

* RSA签名

* @param content 待签名数据

* @param privateKey 商户私钥

* @param input_charset 编码格式

*/

public static String sign(String content, String privateKey, String input_charset){

try {

PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64_.decode(privateKey) );

KeyFactory keyf = KeyFactory.getInstance(KEY_ALGORITHM);

PrivateKey priKey = keyf.generatePrivate(priPKCS8);

java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

signature.initSign(priKey);

signature.update(content.getBytes(input_charset));

byte[] signed = signature.sign();

return Base64_.encode(signed);

}catch (Exception e) {

e.printStackTrace();

}

return null;

}



/**

* RSA验签名检查

* @param content 待签名数据

* @param sign 签名值

* @param ali_public_key 支付宝公钥

* @param input_charset 编码格式

*/

public static boolean verify(String content, String sign, String ali_public_key, String input_charset){

try {

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

byte[] encodedKey = Base64_.decode(ali_public_key);

PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

signature.initVerify(pubKey);

signature.update(content.getBytes(input_charset) );

boolean bverify = signature.verify( Base64_.decode(sign) );

return bverify;

} catch (Exception e) {

e.printStackTrace();

}

return false;

}



/**

* 私钥解密

* @param content 密文

* @param private_key 商户私钥

* @param input_charset 编码格式

*/

public static String decrypt(String content, String private_key, String input_charset) throws Exception {

PrivateKey prikey = getPrivateKey(private_key);

Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);

cipher.init(Cipher.DECRYPT_MODE, prikey);

InputStream ins = new ByteArrayInputStream(Base64_.decode(content));

ByteArrayOutputStream writer = new ByteArrayOutputStream();

//rsa解密的字节大小最多是128,将需要解密的内容,按128位拆开解密

byte[] buf = new byte[128];

int bufl;

while ((bufl = ins.read(buf)) != -1) {

byte[] block = null;

if (buf.length == bufl) {

block = buf;

} else {

block = new byte[bufl];

for (int i = 0; i < bufl; i++) {

block[i] = buf[i];

}

}

writer.write(cipher.doFinal(block));

}

return new String(writer.toByteArray(), input_charset);

}



/**

* 公钥加密

* @param data 源数据

* @param publicKey 公钥(BASE64编码)

*/

public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {

byte[] keyBytes = Base64_.decode(publicKey);

X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

Key publicK = keyFactory.generatePublic(x509KeySpec);

// 对数据加密

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.ENCRYPT_MODE, publicK);

int inputLen = data.length;

ByteArrayOutputStream out = new ByteArrayOutputStream();

int offSet = 0;

byte[] cache;

int i = 0;

// 对数据分段加密

while (inputLen - offSet > 0) {

if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {

cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);

} else {

cache = cipher.doFinal(data, offSet, inputLen - offSet);

}

out.write(cache, 0, cache.length);

i++;

offSet = i * MAX_ENCRYPT_BLOCK;

}

byte[] encryptedData = out.toByteArray();

out.close();

return encryptedData;

}



public static String encryptByPublicKeyToStr(byte[] data, String publicKey) throws Exception {

byte[] bytes = encryptByPublicKey(data, publicKey);

String result = Base64_.encode(bytes);

return result;

}



/**

* 得到私钥

* @param key 密钥字符串(经过base64编码)

* @throws Exception

*/

public static PrivateKey getPrivateKey(String key) throws Exception {

byte[] keyBytes;

keyBytes = Base64_.decode(key);

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

return privateKey;

}



public static class Base64_ {

private static final Base64.Decoder decoder = Base64.getDecoder();

private static final Base64.Encoder encoder = Base64.getEncoder();

public static byte[] decode(String key) {

if (key == null) { return null;}

byte[] decode = decoder.decode(key);

return decode;

}

public static String encode(byte[] content) {

if (content == null) {return null;}

String encode = encoder.encodeToString(content);

return encode;

}

}



/**

* 测试

*/

public static void main(String args[]) 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 pubKey = Base64_.encode(publicKey.getEncoded()); //公钥

String priKey = Base64_.encode(privateKey.getEncoded()); //私钥

// System.out.println(pubKey);

// System.out.println(priKey);



//....公钥加密,私钥解密!



String sourceStr = "密码学";

//公钥加密

byte[] ens = RSAUtil.encryptByPublicKey(sourceStr.getBytes(),pubKey);

String encodes = Base64_.encode(ens);

System.out.println(encodes);

//私钥解密

String res2 = RSAUtil.decrypt(encodes, priKey, "UTF-8");

System.out.println(res2);



//....签名验证,私钥签名,公钥验证是否正确!



String source = "id=shoig&name=shoer&age=23dnjlegj;reg"; //模拟请求参数,然后对此请求参数进行签名。



String sign = RSAUtil.sign(source, priKey, "UTF-8");



System.out.println("签名是:"+sign);



// 公钥验证签名是否正确.

// 具体流程是,请求参数+sign发送给公钥方,然后公钥方过滤掉sign,用公钥验证其他参数是否通过。



boolean result = RSAUtil.verify(source, sign, pubKey, "UTF-8");



System.out.println(result);



}

}
回复

使用道具 举报

10

主题

16

帖子

78

积分

注册会员

Rank: 2

积分
78
 楼主| 发表于 2022-6-2 12:34:13 | 显示全部楼层
圆曲线密码算法(ECC)ECC加密原理:
1、用户A选定一条适合加密的椭圆曲线Ep(a,b)(如:y2=x3+ax+b),并取椭圆曲线上一点,作为基点G。
 2、用户A选择一个私有密钥k,并生成公开密钥K=kG。
 3、用户A将Ep(a,b)和点K,G传给用户B。
 4、用户B接到信息后 ,将待传输的明文编码到Ep(a,b)上一点M,并产生一个随机整数r(r<n)。
 5、用户B计算点C1=M+rK;C2=rG。
 6、用户B将C1、C2传给用户A。
 7、用户A接到信息后,计算C1-kC2,结果就是点M。因为
          C1-kC2=M+rK-k(rG)=M+rK-r(kG)=M
   再对点M进行解码就可以得到明文。
回复

使用道具 举报

10

主题

16

帖子

78

积分

注册会员

Rank: 2

积分
78
 楼主| 发表于 2022-6-2 12:34:29 | 显示全部楼层
#include <iostream>
#define Ea 20
#define Eb 4
#define Ep 29
using namespace std;
int fast_pow(int a, int b, int c)
{
    int ans = 1;   ///记录结果
    a = a % c;   ///预处理,使得a处于c的数据范围之下
    while (b != 0)
    {
        if (b & 1)///奇数
        {
            ans = (ans * a) % c;///消除指数为奇数的影响
        }
        b >>= 1;    ///二进制的移位操作,不断的遍历b的二进制位
        a = (a * a) % c;   ///不断的加倍
    }
    return ans;
}
struct point {
    int x;
    int y;
    point():x(0),y(0){}
    point(int a, int b):x(a),y(b) { }
    bool operator==(const point& b) {
        return this->x == b.x && this->y == b.y;
    }
    point operator+(const point& b) {
        point result;
        if (*this == b) {
            long aaa = 3 * this->x * this->x + Ea;
            long bbb = 2 * this->y;
            //int m = (3 * this->x * this->x + Ea) / (2 * this->y) mod Ep;
            long m;
            if (aaa % bbb != 0) {
                m = ((aaa % Ep) * fast_pow(bbb, (Ep - 2), Ep)) % Ep;
            }
            else {
                m = (aaa / bbb) % Ep;
            }
            result.x = (m * m - 2 * this->x) % Ep;
            result.y = (m * (this->x - result.x) - this->y) % Ep;  
        }
        else {
            long aaa = b.y - this->y;
            long bbb = b.x - this->x;
            if (bbb == 0) {
                return point(13, 23);
            }
            long m;
            if (aaa % bbb != 0) {
                m = ((aaa % Ep) * fast_pow(bbb, (Ep - 2), Ep)) % Ep;
            }
            else {
                m = (aaa / bbb) % Ep;
            }
            result.x = (m * m - this->x - b.x) % Ep;
            result.y = (m * (this->x - result.x) - this->y) % Ep;
        }
        if (result.x < 0) {
            result.x += Ep;
        }
        if (result.y < 0) {
            result.y += Ep;
        }
        return result;
    }
    point operator-() {
        this->y = Ep - this->y;
        return *this;
    }
};
void getG(point x,int& G) {
    point Gx = x;
    G = 1;
    int num = 0;
    do{
        cout<<G<<"x:" << Gx.x << " " << Gx.y << endl;
        Gx = Gx + x;
        G++;
    } while (Gx.x != x.x);
    G++;
    cout << G << "x:" << Gx.x << " " << Gx.y << endl;
}
point getNG(point x,int n) {
    point result = x;
    for (int i = 1; i < n; ++i) {
        result = result + x;
    }

    return result;
}
void print(point p) {
    cout << "[" << " " << p.x << "," << p.y << " " << "]" << endl;
}
int main()
{
    //Alice
    //椭圆曲线 E29(20,4) 基点(13,23)
    //第一步,计算椭圆曲线的阶数
    int G;
    point* x=new point(13, 23);
    getG(*x, G);
    cout << "阶数为:" << G << endl;
    //求得G=36
    //第二步,选择一个私有密钥p(p<G)
    int p =25;
    //第三步,公开密钥K=p*(13,23)
    point K = getNG(*x, p);
    //将 曲线 基点 密钥 公开
    cout << "公开密钥:"<< endl;
    print(K);
    //Bob
    //第四步,需要加密的信息msg,并将msg按照某种编码方式编码到曲线上一点M
    int msg = 13;
    cout << "需要加密的信息:" << msg << endl;;
    point M(13,23);

    //第五步,产生一个随机数r<G
    //srand(unsigned(time(NULL)));
    int r = 6;
    //第六步,计算c1=M+r*K
    //           c2=r*(13,23)
    //(c1,c2)
    point c1 = M;
    for (int i = 0; i < r; ++i) {
        c1 = c1 + K;
    }
    point c2=*x;
    for (int i = 1; i < r; ++i) {
        c2 = c2 + *x;
    }
    cout << "密文为:" << endl;;
    print(c1);
    print(c2);

    //Alice解密
    //第七步:计算c1-p*c2
    point c3;
    point c4=*x;
    p = p*r % G;
    for (int i = 1; i < p; ++i) {
        c4 = c4 + *x;
    }
    c3 = c1 + (-c4);
    cout << "明文为:" << c3.x << endl;
    return 0;
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

教学服务系统

GMT+8, 2025-4-30 07:57 , Processed in 0.014315 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表