教学服务系统

 找回密码
 立即注册
搜索
查看: 672|回复: 2

信息计算2019级1班2号孙志慧

[复制链接]

8

主题

19

帖子

114

积分

注册会员

Rank: 2

积分
114
发表于 2022-5-30 20:40:10 | 显示全部楼层 |阅读模式
一、RSA加密/解密和签名/验签过程理解
为了放便理解:把客户端成为A,服务端称为B
·加解密过程简述
A和B进行通信加密,B要先生成一对RSA密钥,B自己持有私钥,给A公钥 ->A使用B的公钥加密要发送的内容,然后B接收到密文后通过自己的私钥解密内容。
·签名验签过程简述
A给B发送消息,A先计算出消息的消息摘要,然后使用自己的私钥加密消息摘要,被加密的消息摘要九时签名(A用自己的私钥给消息摘要加密成为签名)。B收到消息后,也会使用和A相同的方法提取消息摘要,然后用A的公钥解密签名,并于自己计算出来的消息摘要进行比较,如果相同则说明消息是A发送给B的,同时,A也无法否认自己发送消息给B的事实(B使用A的公钥解密签名文件的过程,叫做“验签”)
数字签名档作用:保证数据完整性,机密性和发送方角色的不可抵赖性,加密与千字节和是两套公私钥是不同的
二、实现环境
Visual Studio Code
三、代码
密钥签名
  1. static Map<String, Object> resetGenKeyPair() throws Exception {
  2.     KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
  3.     keyPairGen.initialize(1024);

  4.     KeyPair keyPair            = keyPairGen.generateKeyPair();
  5.     RSAPublicKey publicKey     = (RSAPublicKey) keyPair.getPublic();
  6.     RSAPrivateKey privateKey   = (RSAPrivateKey) keyPair.getPrivate();
  7.     Map<String, Object> keyMap = new HashMap<String, Object>(2);

  8.     keyMap.put(PUBLIC_KEY, publicKey);
  9.     keyMap.put(PRIVATE_KEY, privateKey);
  10.     return keyMap;
  11. }
复制代码

签名
  1. static String sign(String data, String privateKey) throws Exception {
  2.     byte[] keyBytes = Base64.decode(privateKey);
  3.     PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

  4.     KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  5.     PrivateKey privateK   = keyFactory.generatePrivate(pkcs8KeySpec);
  6.     Signature signature   = Signature.getInstance(SIGNATURE_ALGORITHM);

  7.     signature.initSign(privateK);
  8.     signature.update(data.getBytes(ENCODING));
  9.     return Base64.encodeToString(signature.sign());
  10. }
复制代码

验签
  1. static boolean verifySign(String data, String publicKey, String sign) throws Exception {
  2.     try {
  3.         byte[] keyBytes = Base64.decode(publicKey);

  4.         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
  5.         KeyFactory keyFactory      = KeyFactory.getInstance(KEY_ALGORITHM);
  6.         PublicKey publicK          = keyFactory.generatePublic(keySpec);
  7.         Signature signature        = Signature.getInstance(SIGNATURE_ALGORITHM);

  8.         signature.initVerify(publicK);
  9.         signature.update(data.getBytes(ENCODING));

  10.         return signature.verify(Base64.decode(sign));
  11.     } catch (Exception e) {
  12.         throw e;
  13.     }
  14. }
复制代码

公钥加密
  1. static String encryptByPublicKey(String dataStr, String publicKey) throws Exception {
  2.     byte[] data     = dataStr.getBytes(ENCODING);
  3.     byte[] keyBytes = Base64.decode(publicKey);

  4.     X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  5.     KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  6.     Key publicK           = keyFactory.generatePublic(x509KeySpec);
  7.     Cipher cipher         = Cipher.getInstance(keyFactory.getAlgorithm());

  8.     cipher.init(Cipher.ENCRYPT_MODE, publicK);
  9.     int inputLen = data.length;
  10.     ByteArrayOutputStream out = new ByteArrayOutputStream();

  11.     int offSet = 0;
  12.     byte[] cache;
  13.     int i = 0;
  14.     while (inputLen - offSet > 0) {
  15.         if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
  16.             cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
  17.         } else {
  18.             cache = cipher.doFinal(data, offSet, inputLen - offSet);
  19.         }
  20.         out.write(cache, 0, cache.length);
  21.         i++;
  22.         offSet = i * MAX_ENCRYPT_BLOCK;
  23.     }
  24.     byte[] encryptedData = out.toByteArray();
  25.     out.close();
  26.     return Base64.encodeToString(encryptedData);
  27. }
复制代码

私钥加密
  1. static String encryptByPrivateKey(String dataStr, String privateKey) throws Exception {
  2.     byte[] data     = dataStr.getBytes(ENCODING);
  3.     byte[] keyBytes = Base64.decode(privateKey);

  4.     PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  5.     KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  6.     Key privateK          = keyFactory.generatePrivate(pkcs8KeySpec);
  7.     Cipher cipher         = Cipher.getInstance(keyFactory.getAlgorithm());

  8.     cipher.init(Cipher.ENCRYPT_MODE, privateK);
  9.     int inputLen = data.length;
  10.     ByteArrayOutputStream out = new ByteArrayOutputStream();

  11.     int offSet = 0;
  12.     byte[] cache;
  13.     int i = 0;
  14.     while (inputLen - offSet > 0) {
  15.         if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
  16.             cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
  17.         } else {
  18.             cache = cipher.doFinal(data, offSet, inputLen - offSet);
  19.         }
  20.         out.write(cache, 0, cache.length);
  21.         i++;
  22.         offSet = i * MAX_ENCRYPT_BLOCK;
  23.     }
  24.     byte[] encryptedData = out.toByteArray();
  25.     out.close();
  26.     return Base64.encodeToString(encryptedData);
  27. }
复制代码

公钥解密
  1. static String decryptByPublicKey(String encryptedDataStr, String publicKey) throws Exception {
  2.     byte[] encryptedData = Base64.decode(encryptedDataStr);
  3.     byte[] keyBytes      = Base64.decode(publicKey);

  4.     X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  5.     KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  6.     Key publicK = keyFactory.generatePublic(x509KeySpec);
  7.     Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

  8.     cipher.init(Cipher.DECRYPT_MODE, publicK);
  9.     int inputLen = encryptedData.length;
  10.     ByteArrayOutputStream out = new ByteArrayOutputStream();

  11.     int offSet = 0;
  12.     byte[] cache;
  13.     int i = 0;
  14.     while (inputLen - offSet > 0) {
  15.         if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
  16.             cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
  17.         } else {
  18.             cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
  19.         }
  20.         out.write(cache, 0, cache.length);
  21.         i++;
  22.         offSet = i * MAX_DECRYPT_BLOCK;
  23.     }
  24.     byte[] decryptedData = out.toByteArray();
  25.     out.close();
  26.     return new String(decryptedData, ENCODING);
  27. }
复制代码

私钥解密
  1. static String decryptByPrivateKey(String encryptedDataStr, String privateKey) throws Exception {
  2.     byte[] encryptedData = Base64.decode(encryptedDataStr);
  3.     byte[] keyBytes      = Base64.decode(privateKey);

  4.     PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  5.     KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  6.     Key privateK          = keyFactory.generatePrivate(pkcs8KeySpec);
  7.     Cipher cipher         = Cipher.getInstance(keyFactory.getAlgorithm());

  8.     cipher.init(Cipher.DECRYPT_MODE, privateK);
  9.     int inputLen = encryptedData.length;
  10.     ByteArrayOutputStream out = new ByteArrayOutputStream();

  11.     int offSet = 0;
  12.     byte[] cache;
  13.     int i = 0;
  14.     while (inputLen - offSet > 0) {
  15.         if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
  16.             cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
  17.         } else {
  18.             cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
  19.         }
  20.         out.write(cache, 0, cache.length);
  21.         i++;
  22.         offSet = i * MAX_DECRYPT_BLOCK;
  23.     }
  24.     byte[] decryptedData = out.toByteArray();
  25.     out.close();
  26.     return new String(decryptedData, ENCODING);
  27. }
复制代码

回复

使用道具 举报

8

主题

19

帖子

114

积分

注册会员

Rank: 2

积分
114
 楼主| 发表于 2022-5-31 14:17:53 | 显示全部楼层
ECC
椭圆曲线加密(ECC,Elliptic Curves Cryptography)也属于非对称加密公钥算法,与主流的RSA算法相比,ECC算法可以使用较短的密钥达到相同的安全程度。ECC是建立在基于椭圆曲线的离散对数问题上的密码体制,给定椭圆曲线上的一个点G,并选取一个整数k,求解K=kG很容易(注意根据kG求解出来的K也是椭圆曲线上的一个点);反过来,在椭圆曲线上给定两个点K和G,若使K=kG,求整数k是一个难题。ECC就是建立在此数学难题之上,这一数学难题称为椭圆曲线离散对数问题。近年来,ECC逐步进入实际应用,如国家密码管理局颁布的SM2算法就是基于ECC算法的。
ECC的主要优势是在某些情况下它比其他的算法(比如RSA加密算法)使用更小的密钥并提供相当的或更高等级的安全。ECC的另一个优势是可以定义群之间的双线性映射,基于Weil对或是Tate对;双线性映射已经在密码学中发现了大量的应用,例如基于身份的加密。
不过一个缺点是加密和解密操作的实现比其他机制花费的时间长。
比特币也是用的这个。
密钥对生成
选择一个椭圆曲线E:y²=x³+ax+b(modp),构造一个椭圆群Ep(a,b)。
在Ep(a,b)中挑选生成元点G=(x1,y1),G应使得满足nG=O最小的n是一个非常大的素数。
选择一个小于n的整数nA作为其私钥,然后产生其公钥PA=nAG。
注:公开的信息(E,G,n,PA)
IEpI表示椭圆群Ep(a,b)的元素个数,n是IEpI的素因子。满足:
p+1-2根号p<=|Ep|<=p+1+2根号p
加密算法
将m编码成一个数m<p,在椭圆群Ep(a,b)中随机选择一点Pt=(xt,yt);
在区间[1,n-1]内选取一个随机数k,计算点(x1,y1)=kG;
依据接受方的公钥PB计算点(2,y)=kPB;
计算密文C=mxt+yt;
传送加密数据{kG,Pt+kPB,C}给接受方。
解密算法
接受方接受加密数据{kG,Pt+kPB,C}。
接受方使用自己的私钥作如下计算:Pt+kPB-nB(kG)=Pt+k(nBG)-nB(kG)=Pt
计算m=(C-yt)/xt,得明文m。
回复

使用道具 举报

8

主题

19

帖子

114

积分

注册会员

Rank: 2

积分
114
 楼主| 发表于 2022-5-31 14:35:09 | 显示全部楼层
  1.     /**
  2.      * 生成密钥对
  3.      *
  4.      * @param keysize 密钥长度
  5.      * @return
  6.      */
  7.     public static KeyPair generateECCKeyPair(int keysize) {
  8.         try {
  9.             // 获取指定算法的密钥对生成器
  10.             KeyPairGenerator generator = KeyPairGenerator.getInstance(EC_ALGORITHM, EC_PROVIDER);
  11.             // 初始化密钥对生成器(指定密钥长度, 使用默认的安全随机数源)
  12.             generator.initialize(keysize);
  13.             // 随机生成一对密钥(包含公钥和私钥)
  14.             return generator.generateKeyPair();
  15.         } catch (Exception e) {
  16.             e.printStackTrace();
  17.         }
  18.         return null;
  19.     }
复制代码

ECC加解密
  1. /**
  2.      * ECC 加密
  3.      *
  4.      * @param publicKey 公钥
  5.      * @param plain     原文
  6.      * @return 密文
  7.      */
  8.     public static byte[] eccEncrypt(PublicKey publicKey, byte[] plain) {
  9.         try {
  10.             Cipher cipher = Cipher.getInstance(ECIES_ALGORITHM, EC_PROVIDER);
  11.             cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  12.             return cipher.doFinal(plain);
  13.         } catch (Exception e) {
  14.             e.printStackTrace();
  15.         }
  16.         return null;
  17.     }

  18.     /**
  19.      * ECC 解密
  20.      *
  21.      * @param privateKey  私钥
  22.      * @param encrypted   密文
  23.      * @return 原文
  24.      */
  25.     public static byte[] eccDecrypt(PrivateKey privateKey, byte[] encrypted) {
  26.         try {
  27.             Cipher cipher = Cipher.getInstance(ECIES_ALGORITHM, EC_PROVIDER);
  28.             cipher.init(Cipher.DECRYPT_MODE, privateKey);
  29.             return cipher.doFinal(encrypted);
  30.         } catch (Exception e) {
  31.             e.printStackTrace();
  32.         }
  33.         return null;
  34.     }
复制代码

测试
  1. public static void main(String[] args) {
  2.         // 测试文本
  3.         byte[] plain = "123".getBytes();

  4.         // 生成密钥对
  5.         KeyPair keyPair = generateECCKeyPair(256);
  6.         PublicKey publicKey = keyPair.getPublic();
  7.         PrivateKey privateKey = keyPair.getPrivate();

  8.         // 加解密
  9.         byte[] encrypt = eccEncrypt(publicKey, plain);
  10.         byte[] decrypt = eccDecrypt(privateKey, encrypt);
  11.         System.err.println(new String(decrypt).equals(new String(plain)));
  12.     }
复制代码
回复

使用道具 举报

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

本版积分规则

教学服务系统

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

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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