教学服务系统

 找回密码
 立即注册
搜索
查看: 832|回复: 1

信息计算2019级2班16号吴盛盛

[复制链接]

8

主题

17

帖子

134

积分

注册会员

Rank: 2

积分
134
发表于 2022-6-2 22:26:13 | 显示全部楼层 |阅读模式
RSA数字签名算法

   RSA数字签名算法的过程为:A对明文m用解密变换作: (公钥用来加密,私钥用来解密,数字签名是用私钥完成的,所以称为解密变换,这与onu sdk中一致)sº Dk (m)=md mod n,其中d,n为A的私人密钥,只有A才知道它;B收到A的签名后,用A的公钥和加密变换得到明文,因: Ek(s)= Ek(Dk (m))= (md)e mod n,又 deº1 mod j(n)即de=lj(n)+1,根据欧拉定理mj(n)=1 mod n,所以Ek(s)=mlj(n)+1=[mj(n)]em=m mod n。若明文m和签名s一起送给用户B,B可以确信信息确实是A发送的。同时A也不能否认送给这个信息,因为除了A本人外,其他任何人都无法由明文m产生s.因此RSA数字签名方案是可行的。


  1. import javax.crypto.Cipher;
  2. import java.io.ByteArrayOutputStream;
  3. import java.security.*;
  4. import java.security.interfaces.RSAPrivateKey;
  5. import java.security.interfaces.RSAPublicKey;
  6. import java.security.spec.PKCS8EncodedKeySpec;
  7. import java.security.spec.X509EncodedKeySpec;
  8. import java.util.ArrayList;
  9. import java.util.Base64;
  10. import java.util.List;

  11. public class RSAUtils {

  12.     // 加密算法
  13.     private final static String ALGORITHM_RSA = "RSA";

  14.     /**
  15.      * 直接生成公钥、私钥对象
  16.      *
  17.      * @param modulus
  18.      *
  19.      * @throws NoSuchAlgorithmException
  20.      *
  21.      */
  22.     public static List<Key> getRSAKeyObject(int modulus) throws NoSuchAlgorithmException{

  23.         List<Key> keyList = new ArrayList<>(2);
  24.         // 创建RSA密钥生成器
  25.         KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM_RSA);
  26.         // 设置密钥的大小,此处是RSA算法的模长 = 最大加密数据的大小
  27.         keyPairGen.initialize(modulus);
  28.         KeyPair keyPair = keyPairGen.generateKeyPair();
  29.         // keyPair.getPublic() 生成的是RSAPublic的是咧
  30.         keyList.add(keyPair.getPublic());
  31.         // keyPair.getPrivate() 生成的是RSAPrivateKey的实例
  32.         keyList.add(keyPair.getPrivate());
  33.         return keyList;
  34.     }

  35.     /**
  36.      * 生成公钥、私钥的字符串
  37.      * 方便传输
  38.      *
  39.      * @param modulus 模长
  40.      * @return
  41.      * @throws NoSuchAlgorithmException
  42.      */
  43.     public static List<String> getRSAKeyString(int modulus) throws NoSuchAlgorithmException{

  44.         List<String> keyList = new ArrayList<>(2);
  45.         KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM_RSA);
  46.         keyPairGen.initialize(modulus);
  47.         KeyPair keyPair = keyPairGen.generateKeyPair();
  48.         String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
  49.         String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
  50.         keyList.add(publicKey);
  51.         keyList.add(privateKey);
  52.         return keyList;
  53.     }

  54.     // Java中RSAPublicKeySpec、X509EncodedKeySpec支持生成RSA公钥
  55.     // 此处使用X509EncodedKeySpec生成
  56.     public static RSAPublicKey getPublicKey(String publicKey) throws Exception {

  57.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
  58.         byte[] keyBytes = Base64.getDecoder().decode(publicKey);
  59.         X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
  60.         return (RSAPublicKey) keyFactory.generatePublic(spec);
  61.     }

  62.     // Java中只有RSAPrivateKeySpec、PKCS8EncodedKeySpec支持生成RSA私钥
  63.     // 此处使用PKCS8EncodedKeySpec生成
  64.     public static RSAPrivateKey getPrivateKey(String privateKey) throws Exception {

  65.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
  66.         byte[] keyBytes = Base64.getDecoder().decode(privateKey);
  67.         PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
  68.         return (RSAPrivateKey) keyFactory.generatePrivate(spec);
  69.     }

  70.     /**
  71.      * 公钥加密
  72.      *
  73.      * @param data
  74.      * @param publicKey
  75.      * @return
  76.      * @throws Exception
  77.      */
  78.     public static String encryptByPublicKey(String data, RSAPublicKey publicKey)
  79.             throws Exception {
  80.         Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
  81.         cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  82.         // 模长n转换成字节数
  83.         int modulusSize = publicKey.getModulus().bitLength() / 8;
  84.         // PKCS Padding长度为11字节,所以实际要加密的数据不能要 - 11byte
  85.         int maxSingleSize = modulusSize - 11;
  86.         // 切分字节数组,每段不大于maxSingleSize
  87.         byte[][] dataArray = splitArray(data.getBytes(), maxSingleSize);
  88.         ByteArrayOutputStream out = new ByteArrayOutputStream();
  89.         // 分组加密,并将加密后的内容写入输出字节流
  90.         for (byte[] s : dataArray) {
  91.             out.write(cipher.doFinal(s));
  92.         }
  93.         // 使用Base64将字节数组转换String类型
  94.         return Base64.getEncoder().encodeToString(out.toByteArray());
  95.     }

  96.     /**
  97.      * 私钥解密
  98.      *
  99.      * @param data
  100.      * @param privateKey
  101.      * @return
  102.      * @throws Exception
  103.      */
  104.     public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey)
  105.             throws Exception {
  106.         Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
  107.         cipher.init(Cipher.DECRYPT_MODE, privateKey);
  108.         // RSA加密算法的模长 n
  109.         int modulusSize = privateKey.getModulus().bitLength() / 8;
  110.         byte[] dataBytes = data.getBytes();
  111.         // 之前加密的时候做了转码,此处需要使用Base64进行解码
  112.         byte[] decodeData = Base64.getDecoder().decode(dataBytes);
  113.         // 切分字节数组,每段不大于modulusSize
  114.         byte[][] splitArrays = splitArray(decodeData, modulusSize);
  115.         ByteArrayOutputStream out = new ByteArrayOutputStream();
  116.         for(byte[] arr : splitArrays){
  117.             out.write(cipher.doFinal(arr));
  118.         }
  119.         return new String(out.toByteArray());
  120.     }

  121.     /**
  122.      * 按指定长度切分数组
  123.      *
  124.      * @param data
  125.      * @param len 单个字节数组长度
  126.      * @return
  127.      */
  128.     private static byte[][] splitArray(byte[] data,int len){

  129.         int dataLen = data.length;
  130.         if (dataLen <= len) {
  131.             return new byte[][]{data};
  132.         }
  133.         byte[][] result = new byte[(dataLen-1)/len + 1][];
  134.         int resultLen = result.length;
  135.         for (int i = 0; i < resultLen; i++) {
  136.             if (i == resultLen - 1) {
  137.                 int slen = dataLen - len * i;
  138.                 byte[] single = new byte[slen];
  139.                 System.arraycopy(data, len * i, single, 0, slen);
  140.                 result[i] = single;
  141.                 break;
  142.             }
  143.             byte[] single = new byte[len];
  144.             System.arraycopy(data, len * i, single, 0, len);
  145.             result[i] = single;
  146.         }
  147.         return result;
  148.     }


  149. }
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

8

主题

17

帖子

134

积分

注册会员

Rank: 2

积分
134
 楼主| 发表于 2022-6-2 22:39:17 | 显示全部楼层
ECC加密算法
加密过程
1.选取一条椭圆曲线Ep(a,b),并取椭圆曲线上一点作为基点P
2.选定一个大数K作为私钥,并生成公钥Q = K*P
加密:选择一个随机数r(r < n),将消息M生成密文C
1.密文是一个点对,C = (rP,M * rQ)
2.解密:M = r * Q - K * (r * P) = M + r * (K * p) - K * (r * P) = M


  1. import java.util.ArrayList;
  2. import java.util.List;

  3. /**
  4. * @ClassName: Ellipse
  5. * @Description:针对于加密的椭圆曲线,Eq(a,b)由a,b,q三个参数决定
  6. * privateKey为私钥,basePoint为基点,publicKey为公钥;
  7. * rankOfBasePoint为基点的阶,rankOfEllipse为Ellipse的阶;
  8. * multiPoint(k,P)更新私钥和基点,返回公钥;
  9. * getAllPointsOnEllipse()返回所有平常点;
  10. * getRankOfBasePoint()返回基点的阶;
  11. * setPrivateKey(k)设置私钥;
  12. * setBasePoint(P)设置基点;
  13. * getPublicKey()返回公钥;
  14. * @author: dong.yanchao
  15. * @date: 2018年8月14日 10点42分
  16. * @Copyright: v2
  17. */
  18. public class Ellipse {
  19.         //Eq(a,b),椭圆曲线的三个参数
  20.         private int a;
  21.         private int b;
  22.         private int q;

  23.         //私钥
  24.         private long privateKey;
  25.         //基点
  26.         private String basePoint;
  27.         //公钥
  28.         private String publicKey;
  29.        
  30.         //基点的阶
  31.         private long rankOfBasePoint;
  32.         //Ellipse的阶
  33.         private long rankOfEllipse;
  34.         //Ellipse上的所有平常点
  35.         private List<String> allPoints;
  36.        
  37.         public Ellipse(int a, int b, int q) {
  38.                 this.a = a;
  39.                 this.b = b;
  40.                 this.q = q;
  41.                 this.allPoints = this.getAllPointsOnEllipse();
  42.                 this.rankOfEllipse = this.allPoints.size() + 1;
  43.         }
  44.         public int getA() {
  45.                 return a;
  46.         }
  47.         public void setA(int a) {
  48.                 this.a = a;
  49.         }
  50.         public int getB() {
  51.                 return b;
  52.         }
  53.         public void setB(int b) {
  54.                 this.b = b;
  55.         }
  56.         public int getQ() {
  57.                 return q;
  58.         }
  59.         public void setQ(int q) {
  60.                 this.q = q;
  61.         }
  62.         //返回私钥
  63.         public long getPrivateKey() {
  64.                 return privateKey;
  65.         }
  66.         //重置私钥
  67.         public void setPrivateKey(long k) {
  68.                 this.privateKey = k;
  69.         }
  70.         //返回基点
  71.         public String getBasePoint() {
  72.                 return basePoint;
  73.         }
  74.         //重置基点
  75.         public void setBasePoint(String p) {
  76.                 basePoint = p;
  77.                 this.rankOfBasePoint = getRankOfBasePoint();
  78.         }
  79.         //返回公钥
  80.         public String getPublicKey() {
  81.                 return publicKey;
  82.         }
  83.         //返回Ellipse的阶
  84.         public long getRankOfEllipse() {
  85.                 return rankOfEllipse;
  86.         }
  87.         //返回所有Ellipse的平常点,不包括无穷远点
  88.         public List<String> getAllPoints() {
  89.                 return allPoints;
  90.         }
  91.         public static void main(String[] args) {
  92. //                Ellipse algorithm = new Ellipse(1,1,23);//E23(1,1)
  93. //                String s = "3v10";//基点G(3,10)
  94. //                for (int j = 0; j < 100; j++) {
  95. //                        String multiPoint = algorithm.multiPoint(j+1, s);
  96. //                        System.out.println(j+1+":"+multiPoint);
  97. //                        if(multiPoint.equals("0v0"))break;
  98. //                }
  99.                
  100. //                Ellipse algorithm = new Ellipse(1,1,19);//E19(1,1)
  101. //                String s = "10v2";//基点G(10,2)
  102. //                String multiPoint = algorithm.multiPoint(2,s);
  103. //                System.out.println(multiPoint);

  104. //                List<String> allPointsOnEllipse = algorithm.getAllPointsOnEllipse();
  105. //                for (String string : allPointsOnEllipse) {
  106. //                        System.out.println(string);
  107. //                }
  108.                 Ellipse algorithm = new Ellipse(1,1,23);//Eq(a,b)
  109.                 System.out.println(algorithm.getAllPoints());//所有平常点
  110.                 System.out.println(algorithm.getRankOfEllipse());//Ellipse的阶
  111.                 algorithm.setPrivateKey(8);//设置私钥
  112.                 algorithm.setBasePoint("3v10");//设置基点
  113.                 System.out.println(algorithm.getRankOfBasePoint());//基点的阶
  114.                 algorithm.multiPoint(algorithm.getPrivateKey(), algorithm.getBasePoint());
  115.                 System.out.println(algorithm.getPublicKey());//返回公钥
  116.                
  117.         }
  118.        
  119.         /**
  120.          * @Title: multiPoint
  121.          * @Description:
  122.          * 倍点运算,给定一个点P,按照k的二进制展开进行计算
  123.          * @return: String,"XvY"形式,表示点(x,y)
  124.          */
  125.         public String multiPoint(long k,String P) {
  126.                 List<Byte> bins = new ArrayList<Byte>();//k的二进制展开
  127.                 if (k == 0)return "0v0";
  128.                 while (k != 0) {
  129.                         byte tmp = (byte) (k % 2);
  130.                         bins.add(tmp);
  131.                         k /= 2;
  132.                 }
  133.                 String Q = "0v0";
  134.                 for (int i = bins.size() - 1; i >= 0; i--) {
  135.                         Q = doublePoint(Q);//Q=2Q
  136.                         if (bins.get(i) == 1)Q = pAddP(Q, P);//Q=Q+P
  137.                 }
  138.                
  139.                 this.publicKey = Q;
  140.                 return Q;
  141.         }
  142.        
  143.         /**
  144.          * @Title: doublePoint
  145.          * @Description: 计算一个点p的2倍
  146.          * @param: p 被计算的点
  147.          * @return: String,"XvY"形式,表示点(x,y)
  148.          */
  149.         public String doublePoint(String p) {
  150.                 String[] vp = p.split("v");
  151.                 int x1 = Integer.parseInt(vp[0]);
  152.                 int y1 = Integer.parseInt(vp[1]);
  153.                 if (y1 == 0)return "0v0";//分母为0
  154.                
  155.                 long numer = 3 * x1 * x1 + a;//分子
  156.                 long denom = 2 * y1;//分母
  157.                 denom = inv(denom, q);//计算分母的逆元
  158.                 denom = AmodB(denom,q);
  159.                 long slope = (long)AmodB(numer*denom,q);
  160.                 long x11 = AmodB(slope*slope-2*x1,q);
  161.                 int Xr = (int) x11;// 横坐标
  162.                 long y11 = AmodB(slope*(x1-Xr)-y1,q);
  163.                 int Yr = (int) y11;// 纵坐标
  164.                 return Xr + "v" + Yr;// 返回2倍点的新坐标
  165.         }

  166.         /**
  167.          * @Title: pAddP
  168.          * @Description: 计算两个不同点相加
  169.          * @param: P1
  170.          * @param: P2
  171.          * @return: String,"XvY"形式,表示点(x,y)
  172.          */
  173.         public String pAddP(String P1, String P2) {
  174.                 if (P2.equals(P1)) return doublePoint(P1);// 如果两个点一致,直接调用doublePoint运算
  175.                
  176.                 String[] vp = P1.split("v");
  177.                 String[] vq = P2.split("v");
  178.                 if (vp[0].equals(vq[0]))return "0v0";//x1==x2,不可能

  179.                 if (P2.equals("0v0"))return P1;
  180.                 if (P1.equals("0v0"))return P2;
  181.                 //P1和P2全不为0v0,则展开如下计算
  182.                 int x1 = Integer.parseInt(vp[0]);
  183.                 int y1 = Integer.parseInt(vp[1]);

  184.                 int x2 = Integer.parseInt(vq[0]);
  185.                 int y2 = Integer.parseInt(vq[1]);

  186.                 long DValueY = AmodB(y2-y1,q);
  187.                 long DValueX = AmodB(x2-x1,q);
  188.                 DValueX = inv(DValueX, q);//取倒数
  189.                 DValueX = AmodB(DValueX,q);
  190.                 long slope = AmodB(DValueY*DValueX,q);//斜率
  191.                 long xrr = AmodB(slope*slope-x1-x2,q);
  192.                
  193.                 int xr = (int) xrr;
  194.                 long y11 = AmodB(slope*(x1-xr)-y1,q);
  195.                 int yr = (int) y11;
  196.                 return xr + "v" + yr;
  197.         }
  198.         /**
  199.          * @Title: inv 取倒数
  200.          * @Description: 计算逆元,理解为在mod r2的基础上,“取倒数”的意思
  201.          * 假设得到的结果为res,则有res*r1 == 1 (mod r2)恒成立
  202.          */
  203.         public long inv(long r1,long r2){
  204.                 return extraEuclid(r1,r2,1,0);
  205. //                return AexpB(r1,r2-2);
  206.         }
  207.         /**
  208.          * @Title: extraEuclid 扩展的欧几里得算法
  209.          */
  210.         public long extraEuclid(long r1, long r2, long x1, long x2) {
  211.                 long qr = r1 / r2;
  212.                 long r = r1 % r2;
  213.                 long x = x1 - qr * x2;
  214.                 if (r == 1) return x;
  215.                 return extraEuclid(r2, r, x2, x);
  216.         }
  217.         /**
  218.          * @Title: AexpB Fq上的指数运算
  219.          * @Description: 计算a^b的值
  220.          * @return: long ,返回值范围[0,b-1]
  221.          */
  222.         public long AexpB(long g,long e){
  223.                 if(AmodB(e,q)==0)return 1l;
  224.                 List<Byte> bins = new ArrayList<Byte>();//e的二进制展开
  225.                 while (e != 0) {
  226.                         byte tmp = (byte) (e % 2);
  227.                         bins.add(tmp);
  228.                         e /= 2;
  229.                 }
  230.                 long x = g;
  231.                 for (int i = bins.size() - 2; i >= 0; i--) {
  232.                         x = AmodB(x*x,q);//x=x^2
  233.                         if (bins.get(i) == 1)x = AmodB(g*x,q);//x=g*x
  234.                 }
  235.                 return x;
  236.         }
  237.         /**
  238.          * @Title: AmodB 整数求模运算
  239.          * @Description: 计算a mod b的值
  240.          * @return: long ,返回值范围[0,b-1]
  241.          */
  242.         public long AmodB(long a, long b) {
  243.                 long res = a % b;
  244.                 if(res<0)return res+b;
  245.                 return res;
  246.         }
  247.        
  248.         /**
  249.          * @Title: getAllPointsOnEllipse 求椭圆曲线上所有的平常点,不包括无穷远点
  250.          * @Description: 平常点(X,Y),X和Y都属于Fp有限域,(X,Y)满足Eq(a,b)方程
  251.          * @return: List<String>,点的集合,每个String采用"XvY"的格式,即平常点(X,Y)
  252.          */
  253.         public List<String> getAllPointsOnEllipse(){
  254.                 List<String> retPoints = new ArrayList<String>();
  255.                 for(long X = 0;X<q;X++){
  256.                         long A = AmodB(X*X*X+a*X+b,q);
  257.                         if(A==0){
  258.                                 retPoints.add(new String(X+"v0"));
  259.                                 continue;
  260.                         }
  261.                         long Y = square(A);
  262.                         if(q==Y)continue;
  263.                         retPoints.add(new String(X+"v"+Y));
  264.                         retPoints.add(new String(X+"v"+(q-Y)));
  265.                 }
  266.                 return retPoints;
  267.         }
  268.         /**
  269.          * @Title: square 整数求平方根的运算
  270.          * @param g 满足[0,q)的整数
  271.          * @Description: ret为g的平方根,有ret*ret=g(mod q)恒成立,若ret成立,则q-ret也成立
  272.          * @return: long ,返回任意一个值,返回值范围[0,q-1],另一个为q-ret;返回q,则代表g不存在平方根
  273.          */
  274.         public long square(long g){
  275.                 if(g<0||g>=q){
  276.                         System.err.print("square的参数g应满足[0,q)");
  277.                         System.exit(0);
  278.                 }
  279.                 if(g==0)return 0;
  280.                 long u = q/4;
  281.                 long ret = AexpB(g,u+1);
  282.                 if(AmodB(ret*ret,q)==g)return ret;
  283.                 return q;
  284.         }
  285.         /**
  286.          * @Title: getRankOfBasePoint 求基点的阶
  287.          * @Description: 设P为基点,nP=O,则n为P的阶。有限域上P的阶一定存在,可证明
  288.          */
  289.         public long getRankOfBasePoint(){
  290.                 long ret = -1L;
  291.                 String G = this.basePoint;
  292.                 for(long i = 2;;i++){
  293.                         G=pAddP(G,this.basePoint);
  294.                         if(G.equals("0v0")){
  295.                                 ret = i;
  296.                                 break;
  297.                         }
  298.                 }
  299.                 return ret;
  300.         }
  301.        
  302. }

复制代码



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

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

本版积分规则

教学服务系统

GMT+8, 2025-4-30 01:31 , Processed in 0.017430 second(s), 27 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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