精华内容
下载资源
问答
  • Java实现加密算法

    2021-07-30 15:33:31
    一、常用的加密算法及简略介绍 常用加密算法 Base64 严格来说只是一种编码方式,并不算是加密算法 Base64 编码是从二进制到字符的过程,用 64 个字符来表示任意的二进制数据,常用于在 HTTP 加密,图片编码传输等 ...

    一、常用的加密算法及简略介绍

    1、常用加密算法

    Base64编码

    严格来说只是一种编码方式,并不算是加密算法
    Base64 编码是从二进制到字符的过程,用 64 个字符来表示任意的二进制数据,常用于在 HTTP 加密,图片编码传输等

    MD5信息摘要算法

    Message Digest algorithm 5
    一般用于确保信息的传输完整一致性,校验传输的数据是否被修改,一旦原始信息被修改,生成的 MD5 值将会变得很不同

    SHA密码散列函数家族

    FIPS 所认证的安全散列算法,和 MD5 类似,都是对文本进行散列,产生一定长度的散列值

    HMAC散列消息鉴别码

    Hash Message Authentication Code
    是一种通过特别计算方式之后产生的消息认证码(MAC),使用密码散列函数,同时结合一个加密密钥。它可以用来保证数据的完整性,同时可以用来作某个消息的身份验证。

    2、对称加密

    对称加密的意思就是信息收发都有相同的一把钥匙,消息的加密解密都用这把钥匙进行。

    1、DES
    Data Encryption Standard,数据加密标准,速度较快,适用于加密大量数据的场合。
    2、3DES
    DES的升级版,原理和DES一样,需要处理三个密钥
    3、AES
    Advanced Encryption Standard,高级加密标准,是下一代的加密算法标准,速度快,安全级别高;

    3、非对称加密

    非对称加密算法是一种密钥的保密方法。
    非对称加密算法需要两个密钥:
    公开密钥(publickey)和私有密钥(privatekey)。
    公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。

    1、RSA
    名称来源于发明这个算法的三个人的姓氏组成,算法大致内容就是对极大整数进行因式分解
    这种算法非常可靠,密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长 RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还无法破解(至少没人公开宣布)。因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全。
    2、DSA
    Digital Signature Algorithm,数字签名算法,是一种标准的 DSS(数字签名标准);
    3、ECC
    Elliptic Curves Cryptography,椭圆曲线密码编码学。
    一种建立公开密钥加密的算法,基于椭圆曲线数学。
    ECC的主要优势是在某些情况下它比其他的方法使用更小的密钥——比如RSA加密算法——提供相当的或更高等级的安全。ECC的另一个优势是可以定义群之间的双线性映射,基于Weil对或是Tate对;双线性映射已经在密码学中发现了大量的应用,例如基于身份的加密。不过一个缺点是加密和解密操作的实现比其他机制花费的时间长。

    总结

    现在的加密算法大部分情况下是为了验证数据的一致性,例如传递一些参数组的时候,简单的会使用 BASE64 或 MD5 进行加密生成一个签名。复杂点就是 BASE64 编码之后再用 对称密钥再加密一次,达到比较不容易被人篡改的目的
    对于一些支付场景,一般使用非对称加密算法 实现,这样的场景需要的安全性更高。

    二、简单介绍算法示例

    1、Base64

        public static void main(String[] args) throws Exception {
            String data = "即将加密的数据";
    		//base64加密(方式1)
            String encData1 = Base64.encodeBase64String(data.getBytes());
            //base64加密(方式2)
            String encData2 = (new BASE64Encoder()).encodeBuffer(data.getBytes());
            System.out.println("encData1 = "+ encData1);
            System.out.println("encData2 = "+ encData2);
            
            //base64解密(方式1)
            byte[] decData1 = Base64.decodeBase64(encData1);
            byte[] decData2 = Base64.decodeBase64(encData2);
            //base64解密(方式2)
            byte[] decData3 = (new BASE64Decoder()).decodeBuffer(encData1);
            byte[] decData4 = (new BASE64Decoder()).decodeBuffer(encData2);
            System.out.println("decData1 = "+ new String(decData1) );
            System.out.println("decData2 = "+ new String(decData2) );
            System.out.println("decData3 = "+ new String(decData3) );
            System.out.println("decData4 = "+ new String(decData4) );
        }
    

    2、MD5

        public static void main(String[] args) throws Exception {
            String data = "即将加密的数据";
    		// 拿到一个MD5转换器
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(data.getBytes());
            BigInteger encData = new BigInteger(md5.digest());
            //加密之后转换为16进制字符串
            System.out.println("encData = "+ encData.toString(16));
        }
    

    3、SHA

        public static void main(String[] args) throws Exception {
            String data = "即将加密的数据";
    		// 拿到一个SHA转换器
            MessageDigest sha = MessageDigest.getInstance("SHA");
            sha.update(data.getBytes());
            BigInteger encData = new BigInteger(sha.digest());
            //加密之后转换为32进制字符串
            System.out.println("encData = "+ encData.toString(32));
        }
    

    4、HMAC

    
    	/**
         * MAC算法可选以下多种算法
         * <pre>
         * HmacMD5
         * HmacSHA1
         * HmacSHA256
         * HmacSHA384
         * HmacSHA512
         * </pre>
         */
        public static final String KEY_MAC = "HmacMD5";
        
        public static void main(String[] args) throws Exception {
            String data = "即将加密的数据";
            String key = "给定密钥";
            //根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
    		SecretKey secretKey = new SecretKeySpec(key.getBytes(), KEY_MAC);
            //getInstance得到实例
            Mac mac = Mac.getInstance(secretKey.getAlgorithm());
            //用给定密钥初始化 Mac 对象
            mac.init(secretKey);
            // 加密处理
            BigInteger macMd5 = new BigInteger(mac.doFinal(data.getBytes()))
            System.out.println("HMAC:" + macMd5.toString(16));
        }
    

    5、对称加密

    在对称加密算法中,加密与解密的密钥是相同的。
    128 192 256 分别表示密钥的长度。

    填充方式:
    1、NoPadding
      不进行填充,但是这里要求明文必须要是16个字节的整数倍,如果一定要用 NoPadding 的话,那么必须保证原文字节是 8 的倍数,否则的话需要使用其他的填充模式。
    2、PKCS5Padding(默认)
      在明文的末尾进行填充,填充的数据是当前和16个字节相差的数量,例如:

    • 未填充明文
      1,2,3,4,5,6,7,8,9,10,11
    • 填充明文(缺少五个满足16个字节)
      1,2,3,4,5,6,7,8,9,10,11,5,5,5,5,5

    注:使用PKCS7Padding/PKCS5Padding填充时,最后一个字节肯定为填充数据的长度,所以在解密后可以准确删除填充的数据
    3、 ISO10126Padding
       在明文的末尾进行填充,当前和16个字节相差的数量填写在最后,其余字节填充随机数,例如:

    • 未填充明文
      1,2,3,4,5,6,7,8,9,10,11
    • 填充明文(缺少五个满足16个字节)
      1,2,3,4,5,6,7,8,9,10,11,c,b,4,1,5

    模式
      模式是需要制定AES对明文进行加密时使用的模式,一共有五种模式,模式的基本原理是相似的,但是细节上会有一些变化。

    • ECB模式(默认):电码本模式
    • CBC模式:密码分组链接模式
    • CFB模式:密码反馈模式
    • OFB模式:输出反馈模式
    • CTR模式:计算器模式

    如果想详细了解内部原理可以参考:
    https://www.cnblogs.com/better-farther-world2099/p/13293291.html
    https://blog.csdn.net/qq_28205153/article/details/55798628

    1、AES-128-ECB

        public static void main(String[] args) throws Exception {
            /*
             * 此处使用AES-128-ECB加密模式。
             */
            String key = "很随便的密钥";
            // 需要加密的字串
            String data = "即将加密的数据";
            // 加密
            String encData = encrypt(data, key);
            System.out.println("加密后的字串是:" + encData);
            // 解密
            String decData = decrypt(encData, key);
            System.out.println("解密后的字串是:" + decData);
        }
        // 加密
        public static String encrypt(String data, String key) throws Exception {
        	//创建AES的Key生产者
    	   	KeyGenerator kgen = KeyGenerator.getInstance("AES");
    	   	// 利用"很随便的密钥"作为随机数初始化生成一个128字节16位的密钥
    	   	kgen.init(128, new SecureRandom(key.getBytes()));
    	   	//SecureRandom是生成安全随机数序列
    	   	SecretKey secretKey = kgen.generateKey();
    	   	byte[] rKey = secretKey.getEncoded();
    	   	// 转换为AES专用密钥
            SecretKeySpec skeySpec = new SecretKeySpec(rKey, "AES");
            // 创建密码器
            //"算法/模式/补码方式"
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            // 初始化为加密模式的密码器
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
            //此处使用BASE64做转码功能,同时能起到2次加密的作用。
            return new BASE64Encoder().encode(encrypted);
        }
        // 解密
        public static String decrypt(String encData, String key) throws Exception {
            //创建AES的Key生产者
    	   	KeyGenerator kgen = KeyGenerator.getInstance("AES");
    	   	// 利用"很随便的密钥"作为随机数初始化生成一个128字节16位的密钥
    	   	kgen.init(128, new SecureRandom(key.getBytes()));
    	   	//SecureRandom是生成安全随机数序列
    	   	SecretKey secretKey = kgen.generateKey();
    	   	byte[] rKey = secretKey.getEncoded();
            SecretKeySpec skeySpec = new SecretKeySpec(rKey, "AES");
            // 创建密码器
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            // 初始化为解密模式的密码器
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            //先用base64解密
            byte[] encDataByte = cipher.doFinal(new BASE64Decoder().decodeBuffer(encData));
            String decData = new String(encDataByte,StandardCharsets.UTF_8);
            return decData;
        }
    

    2、AES-128-CBC

    使用CBC模式,需要填充一个向量,这里我直接用key来代替。

        public static void main(String[] args) throws Exception {
            /*
             * 此处使用AES-128-CBC加密模式。
             */
            String key = "很随便的密钥";
            // 需要加密的字串
            String data = "即将加密的数据";
            // 加密
            String encData = encrypt(data, key);
            System.out.println("加密后的字串是:" + encData);
            // 解密
            String decData = decrypt(encData, key);
            System.out.println("解密后的字串是:" + decData);
        }
        // 加密
        public static String encrypt(String data, String key) throws Exception {
            //创建AES的Key生产者
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            // 利用"很随便的密钥"作为随机数初始化生成一个128字节16位的密钥
            kgen.init(128, new SecureRandom(key.getBytes()));
            //SecureRandom是生成安全随机数序列
            SecretKey secretKey = kgen.generateKey();
            byte[] rKey = secretKey.getEncoded();
            // 转换为AES专用密钥
            SecretKeySpec skeySpec = new SecretKeySpec(rKey, "AES");
            // 创建密码器
            //"算法/模式/补码方式"
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            //使用CBC模式,需要一个向量iv,可增加加密算法的强度
            IvParameterSpec ips = new IvParameterSpec(rKey);
            // 初始化为加密模式的密码器
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec,ips);
            byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
            //此处使用BASE64做转码功能,同时能起到2次加密的作用。
            return new BASE64Encoder().encode(encrypted);
        }
        // 解密
        public static String decrypt(String encData, String key) throws Exception {
            //创建AES的Key生产者
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            // 利用"很随便的密钥"作为随机数初始化生成一个128字节16位的密钥
            kgen.init(128, new SecureRandom(key.getBytes()));
            //SecureRandom是生成安全随机数序列
            SecretKey secretKey = kgen.generateKey();
            byte[] rKey = secretKey.getEncoded();
            SecretKeySpec skeySpec = new SecretKeySpec(rKey, "AES");
            // 创建密码器
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//使用CBC模式,需要一个向量iv,可增加加密算法的强度
            IvParameterSpec ips = new IvParameterSpec(rKey);
            // 初始化为解密模式的密码器
            cipher.init(Cipher.DECRYPT_MODE, skeySpec,ips);
            //先用base64解密
            byte[] encDataByte = cipher.doFinal(new BASE64Decoder().decodeBuffer(encData));
            String decData = new String(encDataByte,StandardCharsets.UTF_8);
            return decData;
        }
    

    6、非对称加密

    RSA:

    1、私钥加密,公钥解密

    	private static final String DATA = "要加密的数据";
        private static String rsaPublicKey = null;
        private static String rsaPrivateKey = null;
    
        public static void main(String[] args) throws Exception {
            //构建密钥对
            createEnck();
            //私钥加密
            String result = encByPrivateKey(rsaPrivateKey);
            //公钥解密
            decByPublicKey(rsaPublicKey,result);
        }
        //构建密钥对,保存公私钥
        private static void createEnck() throws Exception {
            KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("RSA");
            senderKeyPairGenerator.initialize(512);
            KeyPair keyPair = senderKeyPairGenerator.generateKeyPair();
            //生成公钥
            RSAPublicKey rsaPublicKey1 = (RSAPublicKey) keyPair.getPublic();
            //生成私钥
            RSAPrivateKey rsaPrivateKey1 = (RSAPrivateKey) keyPair.getPrivate();
            //这里也可以不用base64加密,看自己的需求
            rsaPublicKey = Base64.encodeBase64String(rsaPublicKey1.getEncoded());
            rsaPrivateKey = Base64.encodeBase64String(rsaPrivateKey1.getEncoded());
    
            System.out.println("rsaPublicKey = "+rsaPublicKey);
            System.out.println("rsaPrivateKey = "+rsaPrivateKey);
        }
        /**
         * 私钥加密
         */
        private static String encByPrivateKey(String rsaPrivateKey) throws Exception {
            // 在构建密钥对时,对密钥做了base64编码,这里需要先解码
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec((new BASE64Decoder()).decodeBuffer(rsaPrivateKey));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            //创建Cipher对象。
            Cipher cipher = Cipher.getInstance("RSA");
            //初始化为加密模式的密码器
            //用密钥初始化 Cipher
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            //加密
            byte[] bytes = cipher.doFinal(DATA.getBytes());
            String result = Base64.encodeBase64String(bytes);
            System.out.println("私钥加密: " + result);
            return result;
        }
    
        /**
         * 公钥解密
         */
        private static void decByPublicKey(String rsaPublicKey,String result) throws Exception {
            // 这里也需要对公钥进行解码
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec((new BASE64Decoder()).decodeBuffer(rsaPublicKey));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            byte[] bytes = cipher.doFinal(Base64.decodeBase64(result));
            System.out.println("公钥解密: " + new String(bytes));
        }
    

    2、公钥加密,私钥解密

    	private static final String DATA = "要加密的数据";
        private static String rsaPublicKey = null;
        private static String rsaPrivateKey = null;
    
        public static void main(String[] args) throws Exception {
            //构建密钥对
            createEnck();
            //加密
            String result = encByPublicKey(rsaPublicKey);
            //解密
            decByPrivateKey(rsaPrivateKey,result);
        }
        //构建密钥对,保存公私钥
        private static void createEnck() throws Exception {
            KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("RSA");
            senderKeyPairGenerator.initialize(512);
            KeyPair keyPair = senderKeyPairGenerator.generateKeyPair();
            //生成公钥
            RSAPublicKey rsaPublicKey1 = (RSAPublicKey) keyPair.getPublic();
            //生成私钥
            RSAPrivateKey rsaPrivateKey1 = (RSAPrivateKey) keyPair.getPrivate();
            rsaPublicKey = Base64.encodeBase64String(rsaPublicKey1.getEncoded());
            rsaPrivateKey = Base64.encodeBase64String(rsaPrivateKey1.getEncoded());
    
            System.out.println("rsaPublicKey = "+rsaPublicKey);
            System.out.println("rsaPrivateKey = "+rsaPrivateKey);
        }
        /**
         * 公钥加密
         */
        private static String encByPublicKey(String rsaPublicKey) throws Exception {
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec((new BASE64Decoder()).decodeBuffer(rsaPublicKey));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] bytes = cipher.doFinal(DATA.getBytes());
            String result = Base64.encodeBase64String(bytes);
            System.out.println("公钥加密: " + result);
            return result;
        }
    
        /**
         * 私钥解密
         */
        private static void decByPrivateKey(String rsaPrivateKey,String result) throws Exception {
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec((new BASE64Decoder()).decodeBuffer(rsaPrivateKey));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] bytes = cipher.doFinal(Base64.decodeBase64(result));
            System.out.println("私钥解密解密:" + new String(bytes));
        }
    
    展开全文
  • java实现图形学中的椭圆算法

    千次阅读 2005-11-03 20:48:00
    有同学向我要在java实现图形学中的椭圆算法,画直线的算法的程序,在此就献丑了,把上大学时用java写的源代码给先学者做个参考,下面是实现椭圆的算法/*author computer np *test date *(300,100)(400,100) **/...

          有同学向我要在java中实现图形学中的椭圆算法,画直线的算法的程序,在此就献丑了,把上大学时用java写的源代码给先学者做个参考,下面是实现椭圆的算法

    /*author computer np
     *test date
     *(300,100)(400,100)
     *
    */
    import java.awt.*;
    import javax.swing.*;
    import java.awt.event.*;

    public class Lipse
    {
     public static void main(String[] args)
     {
      new MainFrame();
     }
    }
    class MainFrame extends JFrame implements ActionListener
    {
     JPanel pane=new JPanel();
     JTextField T_a,T_b;
     JButton Draw,Show;
     JLabel L_a,L_b;
     int a,b;
     MainFrame()
     {
      super("DrawLipse Window");
      Container con=this.getContentPane();
      con.setLayout(null);
      
      pane.setBounds(20,20,850,550);
      pane.setBackground(new Color(100,156,200));
      con.add(pane);
      
      L_a=new JLabel("请输入长半径:a");
      L_a.setBounds(180,580,100,20);
      con.add(L_a);
      
      L_b=new JLabel("请输入短半径:b");
      L_b.setBounds(180,630,100,20);
      con.add(L_b);
      
      
      T_a=new JTextField();
      T_a.setBounds(300,580,50,20);
      con.add(T_a);
      
      T_b=new JTextField();
      T_b.setBounds(300,630,50,20);
      con.add(T_b);
      
      Draw=new JButton("画椭圆");
      Draw.setBounds(550,580,90,30);
      Draw.addActionListener(this);
      con.add(Draw);
      
      Show=new JButton("显示坐标");
      Show.setBounds(550,620,90,30);
      Show.addActionListener(this);
      con.add(Show);
      
      this.addWindowListener(new CloseWindow());
      this.setBounds(20,20,900,700);
      this.setVisible(true);
      this.setResizable(false);
      
     }/*MainFrame()*/
     public void actionPerformed(ActionEvent e)
     {
         if(e.getSource()==Draw)
         {
          a=Integer.parseInt(T_a.getText().trim());
          b=Integer.parseInt(T_b.getText().trim());
          Line line=new Line(this);
          line.drawLipse(a,b);
         }
         if(e.getSource()==Show)
         {
           Graphics g1=this.pane.getGraphics();
              g1.setColor(Color.PINK);
              g1.drawLine(0,300,920,300);//----x---
              g1.drawLine(410,0,410,720);//----y---
              g1.dispose();
         }
      
     }/*method actionPerformed*/
    }
    class Line
    {
     MainFrame jb;
     Line(MainFrame jb)
     {
      this.jb=jb;
     }
     public void drawLipse(int a,int b)
     {
      int x,y;
      double d1,d2;
      x=0;  y=b;
      d1=b*b+a*a*(-b+0.25);
      Graphics g=jb.pane.getGraphics();
      g.setColor(Color.red);
      g.drawLine(x+410,y+300,x+410,y+300);
      g.drawLine(-x+410,-y+300,-x+410,-y+300);
      g.drawLine(-x+410,y+300,x+410,-y+300);
      g.drawLine(x+410,-y+300,x+410,-y+300);
      try
      {
       while(b*b*(x+1)<a*a*(y-0.5))
                   {
                if(d1<=0)
                  {
                  d1+=b*b*(2*x+3);
                  x++;
                  }
                  else
                  {
                  d1+=(b*b*(2*x+3)+a*a*(-2*y+2));
                  x++;
                  y--;
                  }
                  g.drawLine(x+410,y+300,x+410,y+300);
                  g.drawLine(-x+410,-y+300,-x+410,-y+300);
                  g.drawLine(-x+410,y+300,x+410,-y+300);
                  g.drawLine(x+410,-y+300,x+410,-y+300);
                  Thread.sleep(30);
             }// top of while 
         }catch(Exception e){}
        
      d2=b*b*(x+0.5)*(x+0.5)+a*a*(y-1)*(y-1)-a*a*b*b;
      try
      {
       while(y>0)
          {
         if(d2<=0)
           {
           d2+=b*b*(2*x+2)+a*a*(-2*y+3);
           x++;
              y--;
            }
            else
            {
            d2+=a*a*(-2*y+3);
            y--;
            }
            g.drawLine(x+410,y+300,x+410,y+300);
               g.drawLine(-x+410,-y+300,-x+410,-y+300);
               g.drawLine(-x+410,y+300,x+410,-y+300);
               g.drawLine(x+410,-y+300,x+410,-y+300);
               Thread.sleep(30);
            }/* bottom of while*/
       
         }catch(Exception e){}
      
     } /*DrawLipse*/ 
      
    }
    class CloseWindow extends WindowAdapter
    {
     public void windowClosing(WindowEvent e)
     {
      System.exit(0);
     }
    }

    展开全文
  • 目前,pca算法已经广泛应用于各方面,就拿图像处理,经常做的一件事就是当提取的图像特征维度比较高时,为了简化计算量以及储存空间,需要对这些高维数据进行一定程度上的降维,并尽量保证数据的不失真。先举个例子...

    目前,pca算法已经广泛应用于各方面,就拿图像处理,经常做的一件事就是当提取的图像特征维度比较高时,为了简化计算量以及储存空间,需要对这些高维数据进行一定程度上的降维,并尽量保证数据的不失真。

    先举个例子,方便理解:

    1)对于一个训练集,100个sample(i=1,2,3,...,100),特征Xi是20维.[Xi1,Xi2,Xi3,...Xij,...,Xi20](j=1,2,..,20),那么它可以建立一个20*100的样本矩阵M。

    2)紧接着我们开始求这个样本的协方差矩阵,得到一个20*20的协方差矩阵,计算过程如下:

    •先求解出Xi的平均Xav=(∑xi)/20;

    •对每一个Xi,计算Xi-Xav,即Mi(第 i 行)变为 Mi-Xav,记为Mn;

    •则容易得到协方差矩阵Z为Mn*Mn'( ' 表示转置 ) 。

    3)然后求出这个协方差矩阵Z20x20的特征值和特征向量,一般情况下应该有20个特征值和特征向量,现在根据特征值的大小,取出较大的特征值以及其所对应的特征向量,(假设提取的特征值为较大的5个特征值),那么这5个特征向量就会构成一个20*5的矩阵V,这个矩阵就是我们要求的特征矩阵。

    4)用Mn去乘以V,得到一个base矩阵(*),大小为100x5。

    5)任取一个样本1x100,乘上这个100*5的特征矩阵,就得到了一个1*5的新的样本,显然每个sample的维数下降了,然后再用这个1x5向量去比较相似性。

    注:

    ›上述3)过程中特征值的选取在不确定具体要降到多少维的情况下,一般还可以根据n个特征值之和大于总和的90%进行选取。

    ›上面的(*)处base矩阵的求解不唯一,也可以自行修正。

    大致说完了PCA降维的过程,现在会有人要问为什么只提取特征值较大的几个特征值就可以近似代替原样本矩阵呢。

    下面就讲讲矩阵的特征值和特征向量的数学意义:

    为简单起见,以二维矩阵A=[1 0;0 -1](矩阵的秩为2)为例,以平面上一点(x,y)经过A变换后变为(x',y')若这两点在一条直线在,那么可以理解为矩阵A的作用恰好使得向量[x y]' 只是在原有方向上变换了长度而已,即Ax=λx (x为一列向量).对于A矩阵,容易得到A的两个特征值及相应的特征向量 λ1=1 ,e1=[1 0]' , λ2=-1 ,e2=[0 -1]' ,二维平面上任意一点(x,y)=b1*(1,0)+b2*(0,-1)(b1,b2均为实常数); 那么A[x y]'=A*(b1*e1+b2*e2)=b1*λ1+b2*λ2 =∑biλi;

    把这个公式推广到高维空间,在计算(x',y')对于λ值比较小的特征维可以忽略.

    B=[1 0;0 0.01] ,其中B的两个特征值及相应的特征向量 λ1=1 ,e1=[1 0]' , λ2=0.01 ,e2=[0 1]'

    那么x=[2 3]' 经过B变换为 Bx=[2 0.03]';

    如果我们认为λ2远小于λ1,忽略掉λ2时,Bn=[1 0;0 0],Bnx=[2 0]'≈[2 0.03].

    通俗点讲,pca算法就是去寻找那些在该维度上方差比较大的维,同时忽略比较平均的维度。假如上面所说的X特征向量的第一个元素都为1,那么这一列数据是可以忽略的,因为他并不能起到区分的作用,相反我们是要寻找那些在某一维度分布比较广的维,并提取出来。

    打个比方,平面区域一个斜75度的椭圆,且长轴远大于短轴,那么椭圆上的点在短轴上的分布明显弱于长轴,当短轴远小于长轴时,近似为一条直线,便失去了短轴这个维度。

    cf1345994992cef22d4324b040a0372c.png

    下面贴上一个matlab版的pca算法代码:

    %一个修改后的PCA进行人脸识别的Matlab代码

    clear;

    % calc xmean,sigma and its eigen decomposition

    allsamples=[];%所有训练图像

    for i=1:40

    for j=1:5

    a=imread(strcat('C:\Documents and Settings\Foreigners\桌面\ORL\s',num2str(i),'\',num2str(j),'.bmp'));

    % imshow(a);

    b=a(1:112*92); % b是行矢量 1×N,其中N=10304,提取顺序是先列后行,即从上到下,从左到右

    b=double(b);

    allsamples=[allsamples; b]; % allsamples 是一个M * N 矩阵,allsamples 中每一行数据代表一张图片,其中M=200

    end

    end

    samplemean=mean(allsamples); % 平均图片,1 × N

    for i=1:200 xmean(i,:)=allsamples(i,:)-samplemean; % xmean是一个M × N矩阵,xmean每一行保存的数据是“每个图片数据-平均图片”

    end;

    sigma=xmean*xmean'; % M * M 阶矩阵

    [v d]=eig(sigma);

    d1=diag(d);

    [d2 index]=sort(d1); %以升序排序

    cols=size(v,2);% 特征向量矩阵的列数

    for i=1:cols

    vsort(:,i) = v(:, index(cols-i+1) ); % vsort 是一个M*col(注:col一般等于M)阶矩阵,保存的是按降序排列的特征向量,每一列构成一个特征向量

    dsort(i) = d1( index(cols-i+1) ); % dsort 保存的是按降序排列的特征值,是一维行向量

    end %完成降序排列

    %以下选择90%的能量

    dsum = sum(dsort);

    dsum_extract = 0;

    p = 0;

    while( dsum_extract/dsum < 0.90)

    p = p + 1;

    dsum_extract = sum(dsort(1:p));

    end

    i=1;

    % (训练阶段)计算特征脸形成的坐标系

    while (i<=p && dsort(i)>0)

    base(:,i) = dsort(i)^(-1/2) * xmean' * vsort(:,i); % base是N×p阶矩阵,除以dsort(i)^(1/2)是对人脸图像的标准化,详见《基于PCA的人脸识别算法研究》p31

    i = i + 1;

    end

    % add by wolfsky 就是下面两行代码,将训练样本对坐标系上进行投影,得到一个 M*p 阶矩阵allcoor

    allcoor = allsamples * base;

    accu = 0;

    % 测试过程

    for i=1:40

    for j=6:10 %读入40 x 5 副测试图像

    a=imread(strcat('C:\Documents and Settings\Foreigners\桌面\ORL\s',num2str(i),'\',num2str(j),'.bmp'));

    b=a(1:10304);

    b=double(b);

    tcoor= b * base; %计算坐标,是1×p阶矩阵

    for k=1:200

    mdist(k)=norm(tcoor-allcoor(k,:));

    end;

    %三阶近邻

    [dist,index2]=sort(mdist);

    class1=floor( index2(1)/5 )+1;

    class2=floor(index2(2)/5)+1;

    class3=floor(index2(3)/5)+1;

    %class=class1;%%blue_lg

    if class1~=class2 && class2~=class3

    class="class1";

    elseif class1==class2

    class="class1";

    %elseif class2==class3

    % class="class2";

    end;

    if class==i

    accu=accu+1;

    end;

    end;

    end;

    accuracy=accu/200 %输出识别率

    %zuobiao=[1:100];

    %plot(zuobiao,accuracy);

    PCA的一个python代码:

    from numpy import*

    def pca(dataMat, topNfeat=9999999):

    meanVals = mean(dataMat, axis=0)

    meanRemoved = dataMat - meanVals #remove mean

    covMat = cov(meanRemoved, rowvar=0)

    eigVals,eigVects = linalg.eig(mat(covMat))

    eigValInd = argsort(eigVals) #sort, sort goes smallest to largest

    eigValInd = eigValInd[:-(topNfeat+1):-1] #cut off unwanted dimensions

    redEigVects = eigVects[:,eigValInd] #reorganize eig vects largest to smallest

    lowDDataMat = meanRemoved * redEigVects#transform data into new dimensions

    reconMat = (lowDDataMat * redEigVects.T) + meanVals

    return lowDDataMat, reconMat

    另加几个不错博客文章:

    有一个问题望围观者能解答:

    上文描述的PCA步骤只是一般的PCA步骤,应该用散步矩阵是不是更好点,另外第四步是不是已经得到了降维数据了,第五步就不需要了。

    展开全文
  • 椭圆曲线加密算法 java语言实现 elliptic curve private keys produce DER encodings of PKCS8 PrivateKeyInfo objects and elliptic curve public keys produce DER encodings of X.509 SubjectPublicKeyInfo ...
  • /题目描述 //实现有限域上的椭圆曲线群的点乘运算
  • java采用中点Bresenham算法椭圆
  • 自己编写的java语言描述 椭圆曲线密码系统算法中的点乘运算 ,可以实现nQ运算。初学者可以用来参考 学习
  • SM2椭圆曲线公钥密码算法JAVA实现

    千次阅读 2018-01-10 14:39:00
    import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1...
    package com.zpc.cryptography;
    
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.math.BigInteger;
    import java.util.Enumeration;
    
    
    import org.bouncycastle.asn1.ASN1EncodableVector;
    import org.bouncycastle.asn1.ASN1InputStream;
    import org.bouncycastle.asn1.ASN1Integer;
    import org.bouncycastle.asn1.ASN1Primitive;
    import org.bouncycastle.asn1.ASN1Sequence;
    import org.bouncycastle.asn1.DERInteger;
    import org.bouncycastle.asn1.DEROctetString;
    import org.bouncycastle.asn1.DEROutputStream;
    import org.bouncycastle.asn1.DERSequence;
    import org.bouncycastle.math.ec.ECPoint;
    import org.bouncycastle.util.encoders.Base64;
    
    
    public class SM2Utils {
    
    
    public static byte[] encrypt(byte[] publicKey, byte[] data) throws IOException {
    
        if (publicKey == null || publicKey.length == 0) {
            return null;
        }
    
        if (data == null || data.length == 0) {
            return null;
        }
    
        byte[] source = new byte[data.length];
        System.arraycopy(data, 0, source, 0, data.length);
    
        Cipher cipher = new Cipher();
        SM2 sm2 = SM2.Instance();
        ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);
    
        ECPoint c1 = cipher.Init_enc(sm2, userKey);
        cipher.Encrypt(source);
        byte[] c3 = new byte[32];
        cipher.Dofinal(c3);
    
        DERInteger x = new DERInteger(c1.getX().toBigInteger());
        DERInteger y = new DERInteger(c1.getY().toBigInteger());
        DEROctetString derDig = new DEROctetString(c3);
        DEROctetString derEnc = new DEROctetString(source);
        ASN1EncodableVector v = new ASN1EncodableVector();
        v.add(x);
        v.add(y);
        v.add(derDig);
        v.add(derEnc);
        DERSequence seq = new DERSequence(v);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        DEROutputStream dos = new DEROutputStream(bos);
        dos.writeObject(seq);
        return bos.toByteArray();
    }
    
    public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException {
    
        if (privateKey == null || privateKey.length == 0) {
            return null;
        }
    
        if (encryptedData == null || encryptedData.length == 0) {
            return null;
        }
    
        byte[] enc = new byte[encryptedData.length];
        System.arraycopy(encryptedData, 0, enc, 0, encryptedData.length);
    
        SM2 sm2 = SM2.Instance();
        BigInteger userD = new BigInteger(1, privateKey);
    
        ByteArrayInputStream bis = new ByteArrayInputStream(enc);
        ASN1InputStream dis = new ASN1InputStream(bis);
        ASN1Primitive derObj = dis.readObject();
        //DERObject derObj = dis.readObject();
        ASN1Sequence asn1 = (ASN1Sequence) derObj;
        //DERInteger x = (DERInteger) asn1.getObjectAt(0);
        //DERInteger y = (DERInteger) asn1.getObjectAt(1);
        ASN1Integer x = (ASN1Integer) asn1.getObjectAt(0);
        ASN1Integer y = (ASN1Integer) asn1.getObjectAt(1);
        ECPoint c1 = sm2.ecc_curve.createPoint(x.getValue(), y.getValue(), true);
    
        Cipher cipher = new Cipher();
        cipher.Init_dec(userD, c1);
        DEROctetString data = (DEROctetString) asn1.getObjectAt(3);
        enc = data.getOctets();
        cipher.Decrypt(enc);
        byte[] c3 = new byte[32];
        cipher.Dofinal(c3);
        return enc;
    }
    
    /**
     * 签名
     *
     * @param userId
     * @param privateKey
     * @param sourceData
     * @return
     * @throws IOException
     */
    public static byte[] sign(byte[] userId, byte[] privateKey, byte[] sourceData) throws IOException {
    
        if (privateKey == null || privateKey.length == 0) {
            return null;
        }
    
        if (sourceData == null || sourceData.length == 0) {
            return null;
        }
    
        SM2 sm2 = SM2.Instance();
        BigInteger userD = new BigInteger(privateKey);
        //System.out.println("userD: " + userD.toString(16));
        //System.out.println("");
    
        ECPoint userKey = sm2.ecc_point_g.multiply(userD);
        //System.out.println("椭圆曲线点X: " + userKey.getX().toBigInteger().toString(16));
        //System.out.println("椭圆曲线点Y: " + userKey.getY().toBigInteger().toString(16));
        //System.out.println("");
    
    
        byte[] z = sm2.sm2GetZ(userId, userKey);
        //System.out.println("SM3摘要Z: " + Util.getHexString(z));
        //System.out.println("");
    
        //System.out.println("M: " + Util.getHexString(sourceData));
        //System.out.println("");
    
        SM3Digest sm3 = new SM3Digest();
        sm3.update(z, 0, z.length);
        sm3.update(sourceData, 0, sourceData.length);
        byte[] md = new byte[32];
        sm3.doFinal(md, 0);
    
        //System.out.println("SM3摘要值: " + Util.getHexString(md));
        //System.out.println("");
    
        SM2Result sm2Result = new SM2Result();
        sm2.sm2Sign(md, userD, userKey, sm2Result);
        //System.out.println("r: " + sm2Result.r.toString(16));
        //System.out.println("s: " + sm2Result.s.toString(16));
        //System.out.println("");
    
        DERInteger d_r = new DERInteger(sm2Result.r);
        DERInteger d_s = new DERInteger(sm2Result.s);
        ASN1EncodableVector v2 = new ASN1EncodableVector();
        v2.add(d_r);
        v2.add(d_s);
        DERSequence sign = new DERSequence(v2);
        //DERObject sign = new DERSequence(v2);
        //byte[] signdata = sign.getDEREncoded();
        byte[] signdata = sign.getEncoded();
    
        return signdata;
    }
    
    @SuppressWarnings("unchecked")
    public static boolean verifySign(byte[] userId, byte[] publicKey, byte[] sourceData, byte[] signData) throws IOException {
    
        if (publicKey == null || publicKey.length == 0) {
            return false;
        }
    
        if (sourceData == null || sourceData.length == 0) {
            return false;
        }
    
        SM2 sm2 = SM2.Instance();
        ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);
    
        SM3Digest sm3 = new SM3Digest();
        byte[] z = sm2.sm2GetZ(userId, userKey);
        sm3.update(z, 0, z.length);
        sm3.update(sourceData, 0, sourceData.length);
        byte[] md = new byte[32];
        sm3.doFinal(md, 0);
        //System.out.println("SM3摘要值: " + Util.getHexString(md));
        //System.out.println("");
    
        ByteArrayInputStream bis = new ByteArrayInputStream(signData);
        ASN1InputStream dis = new ASN1InputStream(bis);
        //DERObject derObj = dis.readObject();
        ASN1Primitive derObj = dis.readObject();
        Enumeration<ASN1Integer> e = ((ASN1Sequence) derObj).getObjects();
        BigInteger r = e.nextElement().getValue();
        BigInteger s = e.nextElement().getValue();
        SM2Result sm2Result = new SM2Result();
        sm2Result.r = r;
        sm2Result.s = s;
        //System.out.println("r: " + sm2Result.r.toString(16));
        //System.out.println("s: " + sm2Result.s.toString(16));
        //System.out.println("");
    
    
        sm2.sm2Verify(md, userKey, sm2Result.r, sm2Result.s, sm2Result);
        return sm2Result.r.equals(sm2Result.R);
    }
    
    public static void main(String[] args) throws Exception {
    
    
        String plainText = "message digest";
        //1.源数据数组
        byte[] sourceData = plainText.getBytes();
    
        // 国密规范测试私钥
        String prik = "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263";
        //2.私钥先转十六进制,然后进行Base64编码
        String prikS = new String(Base64.encode(Util.hexToByte(prik)));
        System.out.println("转换后的私钥:prikS====" + prikS);
        //System.out.println("");
    
        // 国密规范测试用户ID
        String userId = "ALICE123@YAHOO.COM";
    
        //获取userId十六进制字符串
        System.out.println("十六进制userId: " + Util.getHexString(userId.getBytes()));
        //System.out.println("");
    
        //System.out.println("签名: ");
        //3.用userId和私钥,对明文数据签名(userid、prik、sourceData)
        byte[] c = SM2Utils.sign(userId.getBytes(), Base64.decode(prikS.getBytes()), sourceData);
        System.out.println("SM2签名后值====" + Util.getHexString(c));
        //System.out.println("");
    
        // 国密规范测试公钥
        String pubk = "040AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857";
        String pubkS = new String(Base64.encode(Util.hexToByte(pubk)));
        System.out.println("转换后的公钥pubkS====" + pubkS);
        //System.out.println("");
    
    
        //System.out.println("验签: ");
        //4.用公钥进行验签(userId、pubk、sourceData、签名数据c)
        boolean vs = SM2Utils.verifySign(userId.getBytes(), Base64.decode(pubkS.getBytes()), sourceData, c);
        System.out.println("验签结果: " + vs);
        //System.out.println("");
    
        //System.out.println("加密: ");
        //5.SM2加密算法
        byte[] cipherText = SM2Utils.encrypt(Base64.decode(pubkS.getBytes()), sourceData);
        System.out.println("SM2加密后结果===" + new String(Base64.encode(cipherText)));
        System.out.println("");
    
        //System.out.println("解密: ");
        //6.SM2解密算法
        plainText = new String(SM2Utils.decrypt(Base64.decode(prikS.getBytes()), cipherText));
        System.out.println("解密后获取的结果===" + plainText);
    
    }
    }

     两个相关JAR从这里下载

    https://pan.baidu.com/s/1ggDmn3H

    https://pan.baidu.com/s/1mkcK3nM

    转载于:https://my.oschina.net/u/568367/blog/1605097

    展开全文
  • 基于椭圆曲线的Diffie-Hellmann算法Java实现 这是一个示例项目,展示了椭圆曲线上的 Diffie-Hellman 算法的功能。 GF2 中的操作是自制的。 在文件 out/parameter.txt 中显示了从 NIST 文档中提取的示例密码安全...
  • 中点画椭圆算法_中点圆算法

    千次阅读 2020-07-29 06:38:39
    中点画椭圆算法 中点圆算法 (Midpoint circle Algorithm) This is an algorithm which is used to calculate the entire perimeter points of a circle in a first octant so that the points of the other octant ...
  • JavaECC 椭圆曲线密码学 - El Gamal (ECCEG) 算法Java 中的实现
  • SM2基于ECC,ECC(Elliptic Curves Cryptography)加密算法是一种公钥加密算法,与主流的RSA算法相比,ECC算法可以使用较短的密钥达到相同的安全程度。近年来,人们对ECC的认识已经不再处于研究阶段,开始逐步进入...
  • java借助bouncycastle库实现ECC双向加密解密算法Utils工具包。
  • Java bouncycastle 包实现椭圆曲线计算

    千次阅读 2019-10-28 13:54:21
    Java bouncycastle 包实现椭圆曲线计算说明示例代码 说明 最近项目需要使用椭圆曲线实现ECDHE秘钥协商算法,然后遇到了一些坑,在这里做个记录 示例代码 引入依赖 <dependency> <groupId>org.bouncy...
  • java常用加密算法

    千次阅读 2016-12-18 19:06:11
    java常用加密算法
  • 现代应用密码学中椭圆曲线求点集E以及点乘算法java代码实现
  • SM2&SM3&SM4国密规范及Java算法实现

    热门讨论 2016-02-17 16:14:59
    包括国密规范PDF格式文档:SM2椭圆曲线公钥密码算法....Java语言软算法实现SM2密码算法加密/解密、签名验签,SM3密码杂凑算法,SM4分组密码算法ECB、CBC模式加密/解密。 软算法实现测试结果均与规范中给出的示例一致。
  • 基于JPBC的SM9算法java实现与测试

    万次阅读 热门讨论 2019-04-18 22:14:39
    基于JPBC的SM9算法java实现与测试
  • 计算机图形学椭圆 椭圆的性质 (Properties of ellipse) Ellipse is defined as the locus of a point in a plane which moves in a plane in such a manner that the ratio of its distance from a fixed point ...
  • 我自己按照国密文档通过Java实现SM2密码算法加密/解密、签名验签,SM3密码杂凑算法,SM4分组密码算法ECB、CBC模式加密/解密。 经过详尽的测试过后没有发现问题,但建议大家在使用时仍进行验证。若有问题请及时反馈,...
  • ECDSA数字签名算法JAVA实现

    千次阅读 2017-12-26 16:58:42
     ECDSA椭圆曲线数字签名算法是针对素数域和伽罗瓦域上的椭圆曲线定义的,在实际中前者更为常用,以下是针对素数域的说明:  1.使用椭圆曲线E其中  椭圆曲线E的模数为p,系数为a和b,生成素数阶q的循环群的点A  2...
  • java 加解密算法

    千次阅读 2016-11-25 09:54:39
    包含java加解密算法(base64,des,3des,aes,pbe,dh,rsa,ElGamal) 包含java摘要算法(md2,md4,md5,sha1,sha2((SHA-224,SHA-256, SHA-384,SHA-512)),mac) 包含签名算法(rsa,dsa,ecdsa)
  • Java 常用加密算法

    2019-04-13 11:23:54
    Java 常用加密算法 参考来源,不止智慧的搬运工。 2018-4-12 于东营市济南路安康宾馆 文章目录Java 常用加密算法分类:单项加密算法复杂的对称加密详解Base64编码解码使用场景MD5理论概述算法使用场景SHA理论概念...
  • SafeCurves-Java的目的是提供用于实现椭圆曲线加密功能的低级原语。 SafeCurves-Java并非旨在实现JCA接口。 SafeCurves-Java的基本目标是帮助为常规使用提供更多种类的可靠密码。 支持的曲线来自。 支持的曲线 ...
  • 非对称加密算法java实现

    千次阅读 2015-03-22 16:32:58
    非对称加密算法的秘钥分为公钥和私钥,公钥和私钥通常情况下是成对出现的,使用公钥加密的数据只有和它对应的私钥才能解开,反之亦然.在非对称加密算法中有一些算法是可以公钥加密,私钥解密的,反过来,私钥加密,公钥解密...
  • 1.Base64编码算法 Base64简介 Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049,上面有MIME的详细规范。 Base64编码...
  • Java 实现 ECC 非对称加密算法加解密和签名验签前言一、ECC 椭圆曲线算法简介二、ECC 加解密代码实例1.生成 ECC 密钥2.ECC 加解密3.测试代码三、ECC 签名验签代码实例1. ECC 签名验签2. 测试代码 前言 文章字数比较...
  • 国密算法Java实现(含详细测试代码) 我自己按照国密文档通过Java实现SM2密码算法加密/解密、签名验签,SM3密码杂凑算法,SM4分组密码算法ECB、CBC模式加密/解密。 经过详尽的测试过后没有发现问题,但建议大家在...
  • 诸如AES、DAS、RSA、ECC椭圆曲线系列等加密算法。 为什么有了商密还要国密。主要原因可能包括: 1、一部分商密的设计中涉及到的一些具体步骤主要是老美的一些强力部门负责的。里面是不是有个什么漏洞啊、后门啊什么...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,674
精华内容 1,869
关键字:

java实现椭圆算法

java 订阅