非对称加密算法_对称加密算法和非对称加密算法 - CSDN
精华内容
参与话题
  • 对称与非对称加密算法

    万次阅读 2018-08-30 10:31:47
    一、对称加密算法   指加密和解密使用相同密钥的加密算法。对称加密算法用来对敏感数据等信息进行加密,常用的算法包括DES、3DES、AES、DESX、Blowfish、、RC4、RC5、RC6。  DES(Data Encryption Standard):...

    一、对称加密算法 

         指加密和解密使用相同密钥的加密算法。对称加密算法用来对敏感数据等信息进行加密,常用的算法包括DES、3DES、AES、DESX、Blowfish、、RC4、RC5、RC6。

         DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合。
         3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高。
         AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高;

                                     

     

    二、非对称加密算法

          指加密和解密使用不同密钥的加密算法,也称为公私钥加密。假设两个用户要加密交换数据,双方交换公钥,使用时一方用对方的公钥加密,另一方即可用自己的私钥解密。常见的非对称加密算法:RSA、DSA(数字签名用)、ECC(移动设备用)、Diffie-Hellman、El Gamal。

            RSA:由 RSA 公司发明,是一个支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的;
            DSA(Digital Signature Algorithm):数字签名算法,是一种标准的 DSS(数字签名标准);
            ECC(Elliptic Curves Cryptography):椭圆曲线密码编码学。

       ECC和RSA相比,在许多方面都有对绝对的优势,主要体现在以下方面:
    (1)抗攻击性强。相同的密钥长度,其抗攻击性要强很多倍。
    (2)计算量小,处理速度快。ECC总的速度比RSA、DSA要快得多。
    (3)存储空间占用小。ECC的密钥尺寸和系统参数与RSA、DSA相比要小得多,意味着它所占的存贮空间要小得多。这对于加密算法在IC卡上的应用具有特别重要的意义。
    (4)带宽要求低。当对长消息进行加解密时,三类密码系统有相同的带宽要求,但应用于短消息时ECC带宽要求却低得多。带宽要求低使ECC在无线网络领域具有广泛的应用前景。

     

    三、散列算法(Hash算法---单向加密算法)
           散列是信息的提炼,通常其长度要比信息小得多,且为一个固定长度。加密性强的散列一定是不可逆的,这就意味着通过散列结果,无法推出任何部分的原始信息。任何输入信息的变化,哪怕仅一位,都将导致散列结果的明显变化,这称之为雪崩效应。散列还应该是防冲突的,即找不出具有相同散列结果的两条信息。具有这些特性的散列结果就可以用于验证信息是否被修改。

           Hash算法:特别的地方在于它是一种单向算法,用户可以通过Hash算法对目标信息生成一段特定长度的唯一的Hash值,却不能通过这个Hash值重新获得目标信息。因此Hash算法常用在不可还原的密码存储、信息完整性校验等。

    单向散列函数一般用于产生消息摘要,密钥加密等,常见的Hash算法:MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1。

           MD5(Message Digest Algorithm 5):是RSA数据安全公司开发的一种单向散列算法,非可逆,相同的明文产生相同的密文。
           SHA(Secure Hash Algorithm):可以对任意长度的数据运算生成一个160位的数值;

           SHA-1与MD5的比较
    因为二者均由MD4导出,SHA-1和MD5彼此很相似。相应的,他们的强度和其他特性也是相似,但还有以下几点不同:
    (1)对强行供给的安全性:最显著和最重要的区别是SHA-1摘要比MD5摘要长32 位。使用强行技术,产生任何一个报文使其摘要等于给定报摘要的难度对MD5是2^(128)数量级的操作,而对SHA-1则是2^(160)数量级的操作。这样,SHA-1对强行攻击有更大的强度。
    (2)对密码分析的安全性:由于MD5的设计,易受密码分析的攻击,SHA-1显得不易受这样的攻击。
    速度:在相同的硬件上,SHA-1的运行速度比MD5慢。

     

    四、 加密算法的选择

    1.由于非对称加密算法的运行速度比对称加密算法的速度慢很多,当我们需要加密大量的数据时,建议采用对称加密算法,提高加解密速度。
    2.对称加密算法不能实现签名,因此签名只能非对称算法。
    3.由于对称加密算法的密钥管理是一个复杂的过程,密钥的管理直接决定着他的安全性,因此当数据量很小时,我们可以考虑采用非对称加密算法。
    4.在实际的操作过程中,我们通常采用的方式是:采用非对称加密算法管理对称算法的密钥,然后用对称加密算法加密数据,这样我们就集成了两类加密算法的优点,既实现了加密速度快的优点,又实现了安全方便管理密钥的优点。
     

             那采用多少位的密钥呢?

             RSA建议采用1024位的数字,ECC建议采用160位,AES采用128为即可。

    展开全文
  • 常用加密算法之非对称加密算法

    万次阅读 2018-03-16 21:55:43
    非对称加密算法 非对称加密算法是一种密钥的保密方法。非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有...

    非对称加密算法

     
    对称加密算法是一种密钥的保密方法。
    非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。
    另一方面,甲方可以使用乙方的公钥对机密信息进行签名后再发送给乙方;乙方再用自己的私匙对数据进行验签。
    甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。 非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要。
    非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。


    工作原理


    1.A要向B发送信息,A和B都要产生一对用于加密
    非对称加密算法非对称加密算法
    和解密的公钥私钥
    2.A的私钥保密,A的公钥告诉B;B的私钥保密,B的公钥告诉A。
    3.A要给B发送信息时,A用B的公钥加密信息,因为A知道B的公钥。
    4.A将这个消息发给B(已经用B的公钥加密消息)。
    5.B收到这个消息后,B用自己的私钥解密A的消息。其他所有收到这个报文的人都无法解密,因为只有B才有B的私钥。



    主要应用


    非对称加密(公钥加密):指加密和解密使用不同密钥的加密算法,也称为公私钥加密。假设两个用户要加密交换数据,双方交换公钥,使用时一方用对方的公钥加密,另一方即可用自己的私钥解密。如果企业中有n个用户,企业需要生成n对密钥,并分发n个公钥。假设A用B的公钥加密消息,用A的私钥签名,B接到消息后,首先用A的公钥验证签名,确认后用自己的私钥解密消息。由于公钥是可以公开的,用户只要保管好自己的私钥即可,因此加密密钥的分发将变得 十分简单。同时,由于每个用户的私钥是唯一的,其他用户除了可以通过信息发送者的公钥来验证信息的来源是否真实,还可以通过数字签名确保发送者无法否认曾发送过该信息。非对称加密的缺点是加解密速度要远远慢于对称加密,在某些极端情况下,甚至能比对称加密慢上1000倍。

    主要功能


    非对称加密体系不要求通信双方事先传递密钥或有任何约定就能完成保密通信,并且密钥管理方便,可实现防止假冒和抵赖,因此,更适合网络通信中的保密通信要求。

    主要算法


    RSAElgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。
    使用最广泛的是RSA算法,Elgamal是另一种常用的非对称加密算法

    算法区别


    对称加密算法与对称加密算法的区别[1] 
    首先,用于消息解密的密钥值与用于消息加密的密钥值不同;
    其次,非对称加密算法比对称加密算法慢数千倍,但在保护通信安全方面,非对称加密算法却具有对称密码难以企及的优势。
    为说明这种优势,使用对称加密算法的例子来强调:
    Alice使用密钥K加密消息并将其发送给Bob,Bob收到加密的消息后,使用密钥K对其解密以恢复原始消息。这里存在一个问题,即Alice如何将用于加密消息的密钥值发送给 Bob?答案是,Alice发送密钥值给Bob时必须通过独立的安全通信信道(即没人能监听到该信道中的通信)。
    这种使用独立安全信道来交换对称加密算法密钥的需求会带来更多问题:
    首先,有独立的安全信道,但是安全信道的带宽有限,不能直接用它发送原始消息。
    其次,Alice和Bob不能确定他们的密钥值可以保持多久而不泄露(即不被其他人知道)以及何时交换新的密钥值
    当然,这些问题不只Alice会遇到,Bob和其他每个人都会遇到,他们都需要交换密钥并处理这些密钥管理问题(事实上,X9.17是一项DES密钥管理ANSI标准[ANSIX9.17])。如果Alice要给数百人发送消息,那么事情将更麻烦,她必须使用不同的密钥值来加密每条消息。例如,要给
    非对称加密算法非对称加密算法
    200个人发送通知,Alice需要加密消息200次,对每个接收方加密一次消息。显然,在这种情况下,使用对称加密算法来进行安全通信的开销相当大。
    非对称加密算法的主要优势就是使用两个而不是一个密钥值:一个密钥值用来加密消息,另一个密钥值用来解密消息。这两个密钥值在同一个过程中生成,称为密钥对。用来加密消息的密钥称为公钥,用来解密消息的密钥称为私钥。用公钥加密的消息只能用与之对应的私钥来解密,私钥除了持有者外无人知道,而公钥却可通过非安全管道来发送或在目录中发布。
    Alice需要通过电子邮件给Bob发送一个机密文档。首先,Bob使用电子邮件将自己的公钥发送给Alice。然后Alice用Bob的公钥对文档加密并通过电子邮件将加密消息发送给Bob。由于任何用Bob 的公钥加密的消息只能用Bob的私钥解密,因此即使窥探者知道Bob的公钥,消息也仍是安全的。Bob在收到加密消息后,用自己的私钥进行解密从而恢复原始文档。

    说了这么多概念性东西,都是方便大家加深理解,想要理解的更仔细可以自行百度。

    下面我会以实战的方式实现常用的非对称加密算法的加密和解密。


    一:DH实现非对称加密算法:

    方式一:jdk的方式实现DH


          // jdk实现:
    public static void jdkDH()
    {
    try 
    {
    // 1.初始化发送方密钥
    KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("DH");
    senderKeyPairGenerator.initialize(512);
    KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();
    // 发送方公钥,发送给接收方(网络、文件。。。)
    byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded();

    // 2.初始化接收方密钥
    KeyFactory receiverKeyFactory = KeyFactory.getInstance("DH");
    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKeyEnc);
    PublicKey receiverPublicKey = receiverKeyFactory.generatePublic(x509EncodedKeySpec);
    DHParameterSpec dhParameterSpec = ((DHPublicKey) receiverPublicKey).getParams();
    KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance("DH");
    receiverKeyPairGenerator.initialize(dhParameterSpec);
    KeyPair receiverKeypair = receiverKeyPairGenerator.generateKeyPair();
    PrivateKey receiverPrivateKey = receiverKeypair.getPrivate();
    byte[] receiverPublicKeyEnc = receiverKeypair.getPublic().getEncoded();

    // 3.密钥构建
    KeyAgreement receiverKeyAgreement = KeyAgreement.getInstance("DH");
    receiverKeyAgreement.init(receiverPrivateKey);
    receiverKeyAgreement.doPhase(receiverPublicKey, true);
    SecretKey receiverDesKey = receiverKeyAgreement.generateSecret("DES");

    KeyFactory senderKeyFactory = KeyFactory.getInstance("DH");
    x509EncodedKeySpec = new X509EncodedKeySpec(receiverPublicKeyEnc);
    PublicKey senderPublicKey = senderKeyFactory.generatePublic(x509EncodedKeySpec);
    KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("DH");
    senderKeyAgreement.init(senderKeyPair.getPrivate());
    senderKeyAgreement.doPhase(senderPublicKey, true);
    SecretKey senderDesKey = senderKeyAgreement.generateSecret("DES");
    if(Objects.equals(receiverDesKey, senderDesKey))
    {
    System.out.println("双方密钥相同。");
    }

    // 4.加密
    Cipher cipher = Cipher.getInstance("DES");
    cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);
    byte[] result = cipher.doFinal(src.getBytes());
    System.out.println("bc dh encrypt:" + Base64.encodeBase64String(result));

    // 5.解密
    cipher.init(Cipher.DECRYPT_MODE, receiverDesKey);
    result = cipher.doFinal(result);
    System.out.println("bc dh decrypt:" + new String(result));

    } catch (Exception e) {

    e.printStackTrace();
    }

    }

    方式二:elgamal方式实现:

    // jdk实现:“私钥解密、公钥加密” , 对于:“私钥加密、公钥解密”有问题,因为Elgamal不支持
    public static void jdkElgamal()
    {
    try 
    {
    // 加入对BouncyCastle支持  
    Security.addProvider(new BouncyCastleProvider());

    // 1.初始化发送方密钥
    AlgorithmParameterGenerato algorithmParameterGenerator=        AlgorithmParameterGenerator.getInstance("Elgamal");
    // 初始化参数生成器
    algorithmParameterGenerator.init(256);
    // 生成算法参数
    AlgorithmParameters algorithmParameters = algorithmParameterGenerator.generateParameters();
    // 构建参数材料
    DHParameterSpec dhParameterSpec = (DHParameterSpec)algorithmParameters.getParameterSpec(DHParameterSpec.class);
    // 实例化密钥生成器
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("Elgamal");
    // 初始化密钥对生成器  
    keyPairGenerator.initialize(dhParameterSpec, new SecureRandom());
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    // 公钥
    PublicKey elGamalPublicKey = keyPair.getPublic();
    // 私钥 
    PrivateKey elGamalPrivateKey = keyPair.getPrivate();
    System.out.println("Public Key:" + Base64.encodeBase64String(elGamalPublicKey.getEncoded()));
    System.out.println("Private Key:" + Base64.encodeBase64String(elGamalPrivateKey.getEncoded()));


    // 2.私钥解密、公钥加密 ---- 加密
    // 初始化公钥  
            // 密钥材料转换
    X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
    // 实例化密钥工厂
    KeyFactory keyFactory2 = KeyFactory.getInstance("Elgamal");
    // 产生公钥
    PublicKey publicKey2 = keyFactory2.generatePublic(x509EncodedKeySpec2);
    // 数据加密 
    // Cipher cipher2 = Cipher.getInstance("Elgamal");
    Cipher cipher2 = Cipher.getInstance(keyFactory2.getAlgorithm()); 
    cipher2.init(Cipher.ENCRYPT_MODE, publicKey2);
    byte[] result2 = cipher2.doFinal(src.getBytes());
    System.out.println("私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result2));

    // 3.私钥解密、公钥加密 ---- 解密
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
    KeyFactory keyFactory5 = KeyFactory.getInstance("Elgamal");
    PrivateKey privateKey5 = keyFactory5.generatePrivate(pkcs8EncodedKeySpec5);
    // Cipher cipher5 = Cipher.getInstance("Elgamal");
    Cipher cipher5 = Cipher.getInstance(keyFactory5.getAlgorithm()); 
    cipher5.init(Cipher.DECRYPT_MODE, privateKey5);
    byte[] result5 = cipher5.doFinal(result2);
    System.out.println("Elgamal 私钥加密、公钥解密 ---- 解密:" + new String(result5));




    /*
    // 私钥加密、公钥解密: 有问题
    // 4.私钥加密、公钥解密 ---- 加密
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
    KeyFactory keyFactory = KeyFactory.getInstance("Elgamal");
    PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    Cipher cipher = Cipher.getInstance("Elgamal");
    cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    byte[] result = cipher.doFinal(src.getBytes());
    System.out.println("私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result));

    // 5.私钥加密、公钥解密 ---- 解密
    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
    keyFactory = KeyFactory.getInstance("Elgamal");
    PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
    cipher = Cipher.getInstance("Elgamal");
    cipher.init(Cipher.DECRYPT_MODE, publicKey);
    result = cipher.doFinal(result);
    System.out.println("Elgamal 私钥加密、公钥解密 ---- 解密:" + new String(result));
    */

    } catch (Exception e) {

    e.printStackTrace();
    }

    }


    方式二:

    //非对称密钥算法
    public static final String KEY_ALGORITHM="ElGamal";


    /**
    * 密钥长度,DH算法的默认密钥长度是1024
    * 密钥长度必须是8的倍数,在160到16384位之间
    * */
    private static final int KEY_SIZE=256;
    //公钥
    private static final String PUBLIC_KEY="ElGamalPublicKey";

    //私钥
    private static final String PRIVATE_KEY="ElGamalPrivateKey";

    /**
    * 初始化密钥对
    * @return Map 甲方密钥的Map
    * */
    public static Map<String,Object> initKey() throws Exception{
    //加入对BouncyCastle支持
    Security.addProvider(new BouncyCastleProvider());
    AlgorithmParameterGenerator apg=AlgorithmParameterGenerator.getInstance(KEY_ALGORITHM);
    //初始化参数生成器
    apg.init(KEY_SIZE);
    //生成算法参数
    AlgorithmParameters params=apg.generateParameters();
    //构建参数材料
    DHParameterSpec elParams=(DHParameterSpec)params.getParameterSpec(DHParameterSpec.class);

    //实例化密钥生成器
    KeyPairGenerator kpg=KeyPairGenerator.getInstance(KEY_ALGORITHM) ;

    //初始化密钥对生成器
    kpg.initialize(elParams,new SecureRandom());

    KeyPair keyPair=kpg.generateKeyPair();
    //甲方公钥
    PublicKey publicKey= keyPair.getPublic();
    //甲方私钥
    PrivateKey privateKey= keyPair.getPrivate();
    //将密钥存储在map中
    Map<String,Object> keyMap=new HashMap<String,Object>();
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);
    return keyMap;

    }


    /**
    * 公钥加密
    * @param data待加密数据
    * @param key 密钥
    * @return byte[] 加密数据
    * */
    public static byte[] encryptByPublicKey(byte[] data,byte[] key) throws Exception{

    //实例化密钥工厂
    KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
    //初始化公钥
    //密钥材料转换
    X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);
    //产生公钥
    PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);

    //数据加密
    Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    return cipher.doFinal(data);
    }
    /**
    * 私钥解密
    * @param data 待解密数据
    * @param key 密钥
    * @return byte[] 解密数据
    * */
    public static byte[] decryptByPrivateKey(byte[] data,byte[] key) throws Exception{
    //取得私钥
    PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(key);
    KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
    //生成私钥
    PrivateKey privateKey=keyFactory.generatePrivate(pkcs8KeySpec);
    //数据解密
    Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    return cipher.doFinal(data);
    }

    /**
    * 取得私钥
    * @param keyMap 密钥map
    * @return byte[] 私钥
    * */
    public static byte[] getPrivateKey(Map<String,Object> keyMap){
    Key key=(Key)keyMap.get(PRIVATE_KEY);
    return key.getEncoded();
    }
    /**
    * 取得公钥
    * @param keyMap 密钥map
    * @return byte[] 公钥
    * */
    public static byte[] getPublicKey(Map<String,Object> keyMap) throws Exception{
    Key key=(Key) keyMap.get(PUBLIC_KEY);
    return key.getEncoded();
    }
    /**
    * @param args
    * @throws Exception 
    */
    public static void main(String[] args) throws Exception {
    //初始化密钥
    //生成密钥对
    Map<String,Object> keyMap=ElGamalTest2.initKey();
    //公钥
    byte[] publicKey=ElGamalTest2.getPublicKey(keyMap);

    //私钥
    byte[] privateKey=ElGamalTest2.getPrivateKey(keyMap);
    System.out.println("公钥:/n"+Base64.encodeBase64String(publicKey));
    System.out.println("私钥:/n"+Base64.encodeBase64String(privateKey));

    System.out.println("================密钥对构造完毕,甲方将公钥公布给乙方,开始进行加密数据的传输=============");
    String str="ElGamal密码交换算法";
    System.out.println("/n===========甲方向乙方发送加密数据==============");
    System.out.println("原文:"+str);

    //乙方使用公钥对数据进行加密
    byte[] code2=ElGamalTest2.encryptByPublicKey(str.getBytes(), publicKey);
    System.out.println("===========乙方使用公钥对数据进行加密==============");
    System.out.println("加密后的数据:"+Base64.encodeBase64String(code2));


    //甲方使用私钥对数据进行解密
    byte[] decode2=ElGamalTest2.decryptByPrivateKey(code2, privateKey);

    System.out.println("甲方解密后的数据:"+new String(decode2));
    }


    方式三:RSA实现非对称加密算法:

    RSA实现非对称也有俩种方式,具体的实现和区别见代码注释:

           方式一:jdk实现

           // jdk实现:私钥加密、公钥解密: 并发时间测试
    public static void RSA()
    {
    try 
    {
    long startTimes = System.currentTimeMillis();


    // 1.初始化发送方密钥
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(512);
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
    final RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
    System.out.println("Public Key:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
    System.out.println("Private Key:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));




    // 2.公钥加密、私钥解密 ---- 加密
    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    result = cipher.doFinal(src.getBytes());
    System.out.println("公钥加密、私钥解密 ---- 加密:" + Base64.encodeBase64String(result));

    long endEncryptTime = System.currentTimeMillis();
    System.out.println("公钥加密、私钥解密 ---- 加密1个时间(单位毫秒):" + (endEncryptTime - startTimes));

    int decryptTimes = 200000;  // 并发解密的个数
    //创建一个可重用固定线程数的线程池
            ExecutorService pool =  Executors.newCachedThreadPool(); // Executors.newFixedThreadPool(1000);
            
    for(int i=0; i<decryptTimes;i++)
    {
    pool.execute(new Thread(new Runnable() {

    @Override
    public void run() {
    try {
    // 3.私钥解密、公钥加密 ---- 解密
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec2 = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
    KeyFactory keyFactory2 = KeyFactory.getInstance("RSA");

    PrivateKey privateKey2 = keyFactory2.generatePrivate(pkcs8EncodedKeySpec2);
    Cipher cipher2 = Cipher.getInstance("RSA");
    cipher2.init(Cipher.DECRYPT_MODE, privateKey2);
    byte[] result2 = cipher2.doFinal(result);
    // System.out.println("公钥加密、私钥解密 ---- 解密:" + new String(result2));
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }));
      
    }

    pool.shutdown();

    while (true) {  
                if (pool.isTerminated()) {  
                    System.out.println("结束了!"); 
                    long endDencryptTime = System.currentTimeMillis() ;
                    long totalTimes = (endDencryptTime - endEncryptTime) / 1000;
                    System.out.println("公钥加密、私钥解密 ---- 并发:" + decryptTimes + "个解密时间(单位秒):" + totalTimes);
                    break;  
                }  
                Thread.sleep(200);  
            }


    } catch (Exception e) {

    e.printStackTrace();
    }

    }


    方式二:

    // jdk实现:
    public static void jdkRSA()
    {
    try 
    {
    // 1.初始化发送方密钥
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(512);
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
    RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
    System.out.println("Public Key:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
    System.out.println("Private Key:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));

    // 2.私钥加密、公钥解密 ---- 加密
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    byte[] result = cipher.doFinal(src.getBytes());
    System.out.println("私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result));

    // 3.私钥加密、公钥解密 ---- 解密
    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
    keyFactory = KeyFactory.getInstance("RSA");
    PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
    cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE, publicKey);
    result = cipher.doFinal(result);
    System.out.println("私钥加密、公钥解密 ---- 解密:" + new String(result));



    // 4.公钥加密、私钥解密 ---- 加密
    X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
    KeyFactory keyFactory2 = KeyFactory.getInstance("RSA");
    PublicKey publicKey2 = keyFactory2.generatePublic(x509EncodedKeySpec2);
    Cipher cipher2 = Cipher.getInstance("RSA");
    cipher2.init(Cipher.ENCRYPT_MODE, publicKey2);
    byte[] result2 = cipher2.doFinal(src.getBytes());
    System.out.println("公钥加密、私钥解密 ---- 加密:" + Base64.encodeBase64String(result2));

    // 5.私钥解密、公钥加密 ---- 解密
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
    KeyFactory keyFactory5 = KeyFactory.getInstance("RSA");
    PrivateKey privateKey5 = keyFactory5.generatePrivate(pkcs8EncodedKeySpec5);
    Cipher cipher5 = Cipher.getInstance("RSA");
    cipher5.init(Cipher.DECRYPT_MODE, privateKey5);
    byte[] result5 = cipher5.doFinal(result2);
    System.out.println("公钥加密、私钥解密 ---- 解密:" + new String(result5));

    } catch (Exception e) {

    e.printStackTrace();
    }

    }


    好了,对称加密算法就总结到这里了,在下一篇中,我将会总结常用的对称加密算法。

    展开全文
  • 最近的文章中多次出现了非对称加密,今天就来分析一下非对称加密算法。   目录: 简介 RSA算法 DSA算法 ECC算法 DH算法     1. 简介   1.1 概念 非对称加密需要两个密钥:公钥 (publickey) 和...

     

     

    最近的文章中多次出现了非对称加密,今天就来分析一下非对称加密的算法。

     

    目录:

    1. 简介
    2. RSA算法
    3. DSA算法
    4. ECC算法
    5. DH算法

     

     

    1. 简介

     

    • 1.1 概念

    非对称加密需要两个密钥:公钥 (publickey) 和私钥 (privatekey)。公钥和私钥是一对,如果用公钥对数据加密,那么只能用对应的私钥解密。如果用私钥对数据加密,只能用对应的公钥进行解密。因为加密和解密用的是不同的密钥,所以称为非对称加密。

    非对称加密算法的保密性好,它消除了最终用户交换密钥的需要。但是加解密速度要远远慢于对称加密,在某些极端情况下,甚至能比对称加密慢上1000倍。

     

    • 1.2 特点

    算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。

     

    • 1.3 工作原理

     

    (1) A 要向 B 发送信息,A 和 B 都要产生一对用于加密和解密的公钥和私钥。
    (2) A 的私钥保密,A 的公钥告诉 B;B 的私钥保密,B 的公钥告诉 A。
    (3) A 要给 B 发送信息时,A 用 B 的公钥加密信息,因为 A 知道 B 的公钥。
    (4) A 将这个消息发给 B (已经用 B 的公钥加密消息)。
    (5) B 收到这个消息后,B 用自己的私钥解密 A 的消息。其他所有收到这个报文的人都无法解密,因为只有 B 才有 B 的私钥。

     

    • 1.4 主要算法

    RSA、Elgamal、背包算法、Rabin、D-H、ECC (椭圆曲线加密算法)。使用最广泛的是 RSA 算法,Elgamal 是另一种常用的非对称加密算法。

     

    • 1.5 应用场景

    (1) 信息加密

    收信者是唯一能够解开加密信息的人,因此收信者手里的必须是私钥。发信者手里的是公钥,其它人知道公钥没有关系,因为其它人发来的信息对收信者没有意义。

    (2) 登录认证

    客户端需要将认证标识传送给服务器,此认证标识 (可能是一个随机数) 其它客户端可以知道,因此需要用私钥加密,客户端保存的是私钥。服务器端保存的是公钥,其它服务器知道公钥没有关系,因为客户端不需要登录其它服务器。

    (3) 数字签名

    数字签名是为了表明信息没有受到伪造,确实是信息拥有者发出来的,附在信息原文的后面。就像手写的签名一样,具有不可抵赖性和简洁性。

    简洁性:对信息原文做哈希运算,得到消息摘要,信息越短加密的耗时越少。

    不可抵赖性:信息拥有者要保证签名的唯一性,必须是唯一能够加密消息摘要的人,因此必须用私钥加密 (就像字迹他人无法学会一样),得到签名。如果用公钥,那每个人都可以伪造签名了。

    (4) 数字证书

    问题起源:对1和3,发信者怎么知道从网上获取的公钥就是真的?没有遭受中间人攻击?

    这样就需要第三方机构来保证公钥的合法性,这个第三方机构就是 CA (Certificate Authority),证书中心。

    CA 用自己的私钥对信息原文所有者发布的公钥和相关信息进行加密,得出的内容就是数字证书。

    信息原文的所有者以后发布信息时,除了带上自己的签名,还带上数字证书,就可以保证信息不被篡改了。信息的接收者先用 CA给的公钥解出信息所有者的公钥,这样可以保证信息所有者的公钥是真正的公钥,然后就能通过该公钥证明数字签名是否真实了。

    这个的实际应用可以看看我之前的文章:网络篇 - https协议中的数据是否需要二次加密,里面讲的比较详细。

     

     

     

    2. RSA算法

     

    • 2.1 简介

    RSA 是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用。

     

    • 2.2 工作流程

    A 要把信息发给 B 为例,确定角色:A 为加密者,B 为解密者。首先由 B 随机确定一个 KEY,称之为私钥,将这个 KEY 始终保存在机器 B 中而不发出来;然后,由这个 KEY 计算出另一个 KEY,称之为公钥。这个公钥的特性是几乎不可能通过它自身计算出生成它的私钥。接下来通过网络把这个公钥传给 A,A 收到公钥后,利用公钥对信息加密,并把密文通过网络发送到 B,最后 B 利用已知的私钥,就能对密文进行解码了。以上就是 RSA 算法的工作流程。

     

    • 2.3 运算速度

    由于进行的都是大数计算,使得 RSA 最快的情况也比 DES 慢上好几倍,无论是软件还是硬件实现。速度一直是 RSA 的缺陷。一般来说只用于少量数据加密。RSA 的速度是对应同样安全级别的对称密码算法的1/1000左右。

    比起 DES 和其它对称算法来说,RSA 要慢得多。实际上一般使用一种对称算法来加密信息,然后用 RSA 来加密比较短的公钥,然后将用 RSA 加密的公钥和用对称算法加密的消息发送给接收方。

    这样一来对随机数的要求就更高了,尤其对产生对称密码的要求非常高,否则的话可以越过 RSA 来直接攻击对称密码。

     

    • 2.4 公钥传递安全

    和其它加密过程一样,对 RSA 来说分配公钥的过程是非常重要的。分配公钥的过程必须能够抵挡中间人攻击。假设 A 交给 B 一个公钥,并使 B 相信这是A 的公钥,并且 C 可以截下 A 和 B 之间的信息传递,那么 C 可以将自己的公钥传给 B,B 以为这是 A 的公钥。C 可以将所有 B 传递给 A 的消息截下来,将这个消息用自己的密钥解密,读这个消息,然后将这个消息再用 A 的公钥加密后传给 A。理论上 A 和 B 都不会发现 C 在偷听它们的消息,今天人们一般用数字认证来防止这样的攻击。

     

    • 2.5 攻击

    (1) 针对 RSA 最流行的攻击一般是基于大数因数分解。1999年,RSA-155 (512 bits) 被成功分解,花了五个月时间(约8000 MIPS 年)和224 CPU hours 在一台有3.2G 中央内存的 Cray C916计算机上完成。

    RSA-158 表示如下:

    1

    395058745832651445264197678006144819960207764603049364541393760515793556265294506836097278424682195350935443058704902519956553357102097992264849779494429556033388495837466721394368393204672181522815830368604993048084925840555281177×  11658823406671259903148376558383270818131012258146392600439520994131344334162924536139

    2009年12月12日,编号为 RSA-768 (768 bits, 232 digits) 数也被成功分解。这一事件威胁了现通行的1024-bit 密钥的安全性,普遍认为用户应尽快升级到2048-bit 或以上。

    RSA-768表示如下:

    1

    12301866845301177551304949583849627207728535695953347921973224521517264005072636575187452021997864693899564749427740638459251925573263034537315482685079170261221429134616704292143116022212404792747377940806653514195974598569021434133347807169895689878604416984821269081770479498371376856891  2431388982883793878002287614711652531743087737814467999489×  3674604366679959042824463379962795263227915816434308764267  6032283815739666511279233373417143396810270092798736308917

    (2) 秀尔算法

    量子计算里的秀尔算法能使穷举的效率大大的提高。由于 RSA 算法是基于大数分解 (无法抵抗穷举攻击),因此在未来量子计算能对 RSA 算法构成较大的威胁。一个拥有 N 量子位的量子计算机,每次可进行2^N 次运算,理论上讲,密钥为1024位长的 RSA 算法,用一台512量子比特位的量子计算机在1秒内即可破解。

     

    • 2.6 例子
        private static final String ALGO = "RSA";
        private static final String CHARSET = "UTF-8";
    
        /*
         * 用于存储随机产生的公钥与私钥
         */
        private static Map<Integer, String> KEY_CACHE = new HashMap<>();
    
        /**
         * 随机生成密钥对
         *
         * @throws NoSuchAlgorithmException
         */
        private static void generateKeyPair() throws NoSuchAlgorithmException {
            // KeyPairGenerator 类用于生成公钥和私钥对,基于RSA算法生成对象
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGO);
            // 初始化密钥对生成器,密钥大小为 96-1024 位
            keyPairGen.initialize(1024, new SecureRandom());
            // 生成一个密钥对,保存在 keyPair 中
            KeyPair keyPair = keyPairGen.generateKeyPair();
            // 得到私钥
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            // 得到公钥
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            String publicKeyString = new String(Base64.getEncoder().encode(publicKey.getEncoded()));
            // 得到私钥字符串
            String privateKeyString = new String(Base64.getEncoder().encode((privateKey.getEncoded())));
            // 将公钥和私钥保存到 Map
            KEY_CACHE.put(0, publicKeyString);
            KEY_CACHE.put(1, privateKeyString);
        }
    
        /**
         * RSA公钥加密
         *
         * @param data       加密字符串
         * @param publicKey 公钥
         * @return 密文
         * @throws Exception 加密过程中的异常信息
         */
        private static String encrypt(String data, String publicKey) throws Exception {
            // base64 编码的公钥
            byte[] decoded = Base64.getDecoder().decode(publicKey);
            RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance(ALGO).generatePublic(new X509EncodedKeySpec(decoded));
            // RSA加密
            Cipher cipher = Cipher.getInstance(ALGO);
            // 公钥加密
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes(CHARSET)));
        }
    
        /**
         * RSA私钥解密
         *
         * @param data        加密字符串
         * @param privateKey 私钥
         * @return 铭文
         * @throws Exception 解密过程中的异常信息
         */
        private static String decrypt(String data, String privateKey) throws Exception {
            byte[] inputByte = Base64.getDecoder().decode(data.getBytes(CHARSET));
            // base64 编码的私钥
            byte[] decoded = Base64.getDecoder().decode(privateKey);
            RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance(ALGO).generatePrivate(new PKCS8EncodedKeySpec(decoded));
            // RSA 解密
            Cipher cipher = Cipher.getInstance(ALGO);
            // 私钥解密
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            return new String(cipher.doFinal(inputByte));
        }
    
        public static void main(String[] args) {
            String originData = "hellp Test Asymmetric encrypt!";
            try {
                generateKeyPair();
                String encryData = encrypt(originData, KEY_CACHE.get(0));
                System.out.println("encryData = " + encryData);
                String decryData = decrypt(encryData, KEY_CACHE.get(1));
                System.out.println("decryData = " + decryData);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    执行输出:

    encryData = Agp72Awcbwy9/8qCFN7VBEwek9LRhjdOqT6JA3MaLOIrEc/VR85vW/q/dL4WOl6ELlyd0L4dieikfw0U94FuH+lyTItEen33lzRszW+xjH8ElSH1/W/3SoAm0r7qRdJ+GoHpRXNGwsnoS77mhYtn743txX1O4bjIdZrLwQZB/6I=
    decryData = hellp Test Asymmetric encrypt!

     

     

     

    3. DSA算法

     

    • 3.1 简介

    DSA (Digital Signature Algorithm) 是 Schnorr 和 ElGamal 签名算法的变种,被美国 NIST 作为 DSS (DigitalSignature Standard)。 DSA 是基于整数有限域离散对数难题的。

    简单的说,这是一种更高级的验证方式,用作数字签名。不单单只有公钥、私钥,还有数字签名。私钥加密生成数字签名,公钥验证数据及签名,如果数据和签名不匹配则认为验证失败。数字签名的作用就是校验数据在传输过程中不被修改,数字签名,是单向加密的升级。

     

    • 3.2 处理过程

    (1) 使用消息摘要算法将发送数据加密生成数字摘要。
    (2) 发送方用自己的私钥对摘要再加密,形成数字签名。 
    (3) 将原文和加密的摘要同时传给对方。 
    (4) 接受方用发送方的公钥对摘要解密,同时对收到的数据用消息摘要算法产生同一摘要。
    (5) 将解密后的摘要和收到的数据在接收方重新加密产生的摘要相互对比,如果两者一致,则说明在传送过程中信息没有破坏和篡改。否则,则说明信息已经失去安全性和保密性。

    具体可以看这篇:网络篇 - https协议中的数据是否需要二次加密

     

    • 3.3 例子
    /**
     * DSA安全编码组件
     */
    public abstract class DSACoder extends Coder {
    
        public static final String ALGORITHM = "DSA";
    
        /**
         * 默认密钥字节数
         *
         * <pre>
         * DSA 
         * Default Keysize 1024  
         * Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive).
         * </pre>
         */
        private static final int KEY_SIZE = 1024;
    
        /**
         * 默认种子
         */
        private static final String DEFAULT_SEED = "0f22507a10bbddd07d8a3082122966e3";
    
        private static final String PUBLIC_KEY = "DSAPublicKey";
        private static final String PRIVATE_KEY = "DSAPrivateKey";
    
        /**
         * 用私钥对信息生成数字签名
         *
         * @param data
         *            加密数据
         * @param privateKey
         *            私钥
         *
         * @return
         * @throws Exception
         */
        public static String sign(byte[] data, String privateKey) throws Exception {
            // 解密由base64编码的私钥
            byte[] keyBytes = decryptBASE64(privateKey);
    
            // 构造PKCS8EncodedKeySpec对象
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
    
            // KEY_ALGORITHM 指定的加密算法
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
    
            // 取私钥匙对象
            PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
    
            // 用私钥对信息生成数字签名
            Signature signature = Signature.getInstance(keyFactory.getAlgorithm());
            signature.initSign(priKey);
            signature.update(data);
    
            return encryptBASE64(signature.sign());
        }
    
        /**
         * 校验数字签名
         *
         * @param data
         *            加密数据
         * @param publicKey
         *            公钥
         * @param sign
         *            数字签名
         *
         * @return 校验成功返回true 失败返回false
         * @throws Exception
         *
         */
        public static boolean verify(byte[] data, String publicKey, String sign)
                throws Exception {
    
            // 解密由base64编码的公钥
            byte[] keyBytes = decryptBASE64(publicKey);
    
            // 构造X509EncodedKeySpec对象
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
    
            // ALGORITHM 指定的加密算法
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
    
            // 取公钥匙对象
            PublicKey pubKey = keyFactory.generatePublic(keySpec);
    
            Signature signature = Signature.getInstance(keyFactory.getAlgorithm());
            signature.initVerify(pubKey);
            signature.update(data);
    
            // 验证签名是否正常
            return signature.verify(decryptBASE64(sign));
        }
    
        /**
         * 生成密钥
         *
         * @param seed
         *            种子
         * @return 密钥对象
         * @throws Exception
         */
        public static Map<String, Object> initKey(String seed) throws Exception {
            KeyPairGenerator keygen = KeyPairGenerator.getInstance(ALGORITHM);
            // 初始化随机产生器
            SecureRandom secureRandom = new SecureRandom();
            secureRandom.setSeed(seed.getBytes());
            keygen.initialize(KEY_SIZE, secureRandom);
    
            KeyPair keys = keygen.genKeyPair();
    
            DSAPublicKey publicKey = (DSAPublicKey) keys.getPublic();
            DSAPrivateKey privateKey = (DSAPrivateKey) keys.getPrivate();
    
            Map<String, Object> map = new HashMap<String, Object>(2);
            map.put(PUBLIC_KEY, publicKey);
            map.put(PRIVATE_KEY, privateKey);
    
            return map;
        }
    
        /**
         * 默认生成密钥
         *
         * @return 密钥对象
         * @throws Exception
         */
        public static Map<String, Object> initKey() throws Exception {
            return initKey(DEFAULT_SEED);
        }
    
        /**
         * 取得私钥
         *
         * @param keyMap
         * @return
         * @throws Exception
         */
        public static String getPrivateKey(Map<String, Object> keyMap)
                throws Exception {
            Key key = (Key) keyMap.get(PRIVATE_KEY);
    
            return encryptBASE64(key.getEncoded());
        }
    
        /**
         * 取得公钥
         *
         * @param keyMap
         * @return
         * @throws Exception
         */
        public static String getPublicKey(Map<String, Object> keyMap)
                throws Exception {
            Key key = (Key) keyMap.get(PUBLIC_KEY);
    
            return encryptBASE64(key.getEncoded());
        }
    }
    

     

     

     

    4. ECC算法

     

    • 4.1 简介

    椭圆加密算法(ECC)是一种公钥加密算法,最初由 Koblitz 和 Miller 两人于1985年提出,其数学基础是利用椭圆曲线上的有理点构成 Abel 加法群上椭圆离散对数的计算困难性。公钥密码体制根据其所依据的难题一般分为三类:大整数分解问题类、离散对数问题类、椭圆曲线类。有时也把椭圆曲线类归为离散对数类。

    ECC 的主要优势是在某些情况下它比其他的方法使用更小的密钥 (比如 RSA),提供相当的或更高等级的安全。ECC 的另一个优势是可以定义群之间的双线性映射,基于 Weil 对或是 Tate 对;双线性映射已经在密码学中发现了大量的应用,例如基于身份的加密。不过一个缺点是加密和解密操作的实现比其他机制花费的时间长。

    ECC 被广泛认为是在给定密钥长度的情况下,最强大的非对称算法,因此在对带宽要求十分紧的连接中会十分有用。

    比特币钱包公钥的生成使用了椭圆曲线算法,通过椭圆曲线乘法可以从私钥计算得到公钥, 这是不可逆转的过程。

     

    • 4.2 优势

    (1) 安全性高,有研究表示160位的椭圆密钥与1024位的 RSA 密钥安全性相同。

    (2) 处理速度快,在私钥的加密解密速度上,ECC 算法比 RSA、DSA 速度更快,存储空间占用小,带宽要求低。 

     

    • 4.3 例子

    https://github.com/esxgx/easy-ecc

    Java 中 Chipher、Signature、KeyPairGenerator、KeyAgreement、SecretKey 均不支持 ECC 算法。

     

     

     

    5. DH算法

     

    • 5.1 简介

    DH,全称为"Diffie-Hellman",它是一种确保共享 KEY 安全穿越不安全网络的方法,也就是常说的密钥一致协议。由公开密钥密码体制的奠基人 Diffie 和 Hellman 所提出的一种思想。简单的说就是允许两名用户在公开媒体上交换信息以生成"一致"的、可以共享的密钥。也就是由甲方产出一对密钥 (公钥、私钥),乙方依照甲方公钥产生乙方密钥对 (公钥、私钥)。

    以此为基线,作为数据传输保密基础,同时双方使用同一种对称加密算法构建本地密钥 (SecretKey) 对数据加密。这样,在互通了本地密钥 (SecretKey) 算法后,甲乙双方公开自己的公钥,使用对方的公钥和刚才产生的私钥加密数据,同时可以使用对方的公钥和自己的私钥对数据解密。不单单是甲乙双方两方,可以扩展为多方共享数据通讯,这样就完成了网络交互数据的安全通讯。

     

    • 5.2 例子

    具体例子可以移步到这篇文章:非对称密码之DH密钥交换算法

     

    展开全文
  • 对称加密,与对称加密的算法是有所不同的,非对称加密算法需要两个密钥,即公开密钥和私有密钥,非对称加密算法在加密和解密过程使用了不同的密钥,对称密钥也称为公钥加密,在密钥对中,其中一个密钥是对外公开...

    非对称加密,与对称加密的算法是有所不同的,非对称加密算法需要两个密钥,即公开密钥和私有密钥,非对称加密算法在加密和解密过程使用了不同的密钥,非对称密钥也称为公钥加密,在密钥对中,其中一个密钥是对外公开的,所有人都可以获取,称为公钥;另外一个密钥是不公开的,称为私钥

    加密算法一般分为对称加密和非对称加密,非对称加密是指为满足安全性需求和所有权验证需求而集成到区块链中的加密技术。非对称加密通常在加密和解密过程中使用两个非对称的密码,分别称为公钥和私钥。非对称密钥对具有两个特点:一是用其中一个密钥(公钥或私钥)加密信息后,只有另一个对应的密钥才能解开;二是公钥可向其他人公开,私钥则保密,其他人无法通过该公钥推算出相应的私钥。

    非对称加密一般划分为三类主要方式:大整数分解问题类、离散对数问题类、椭圆曲线类。大整数分解问题类指用两个较大的质数的乘积作为加密数,由于质数的出现具有不规律性,想要破解只能通过不断试算。离散对数问题类指的是基于离散对数的难解性,利用强的单向散列函数的一种非对称分布式加密算法。椭圆曲线类指利用平面椭圆曲线来计算成组非对称恃殊值,比特币就使用此类加密算法。

    非对称加密技术在区块链的应用场景主要包括信息加密、数字签名和登录认证等。其中信息加密场景主要是由信息发送者(记为A)使用接受者(记为B)的公钥对信息加密后再发送给B,B利用自己的私钥对信息解密。比特币交易的加密即属于此场景。数字签名场景则是由发送者A采用自己的私钥加密信息后发送给B,再由B使用A的公钥对信息解密,从而可确保信息是由A发送的。登录认证场景则是由客户端使用私钥加密登录信息后发送给服务器,后者接收后采用该客户端的公钥解密并认证登录信息。

    存储在区块链上的交易信息是公开的,但是账户身份信息是高度 加密的,只有在数据拥有者授权的情况下才能访问,从而保证了数据 的安全和个人的隐私。区块链系统每个用户都有一对秘钥,一个是公 开的,一个是私有的。通常公钥的密码算法采用的是椭圆曲线算法。 用户可以通过自己的私钥对交易进行签名,同时別的用户可以利用签 名用户的公钥对签名进行验证。

    椭圆曲线指的是由韦尔斯特拉斯(Weierstrass)方程y2+a1xy +a3y=x3+a2x2+a4x+a6所确定的平面曲线。若F是一个域,blob.pngi=1,2 ,...,6。满足式(1-1 )的数偶(x , y )称为F域上的椭圆曲线E的点。F域可以是有理数域,还可以是有限域GF ( Pr )。椭圆曲 线通常用E表示。除了曲线E的所有点外,尚需加上一个叫作无穷远 点的特殊点〇。在椭圆曲线加密(ECC )中,利用了某种恃殊形式的 椭圆曲线,即定义在有限域上的椭圆曲线。其方程如下:

    blob.png

    这里p是素数,a和b为两个小于p的非负整数,它们满足:

    blob.png

    其中,x,y,a,blob.png,则满足式(1-2 )的点(x , y )和—个 无穷点〇就组成了椭圆曲线E。

    椭圆曲线离散对数问题BCDLP定义如下:给定素数p和椭圆曲线E ,对Q=kP ,在已知P,Q的情况下求出小于P的正整数k。可以证已知k和P计算Q比较容易,而由Q和p计算卩则比较困难,至今没有有效的方法来解决这个问题,这就是椭圆曲线加密算法原理之所在。与RSA算法相比,椭圆曲线公钥系统是代替RSA的强有力的竞争者。椭圆曲线加密方法的优点总结如下:

    ·安全性能更高,如160位ECC与1024位RSA、DSA有相同的安全强度。

    ·计算量小,处理速度快,在私钥的处理速度上(解密和签名),ECC远比RSA、DSA快得多。

    ·存储空间占用小,ECC的密钥尺寸和系统参数与RSA、DSA相比要小得多,所以占用的存储空间小得多。

    ·带宽要求低,使得ECC具有广泛的应用前景。

    ECC的这些特点使它必将取代RSA,成为通用的公钥加密算法。比如SET协议的制定者已把它作为下一代SET协议中缺省的公钥密码算法。

    利用椭圆曲线的签名和验证算法,可以保证账号的唯一性和不可冒名顶替性,同时也保证了用户的不可抵赖性。通过这些密码学技术的应用可以使得区块链技术在没有中心服务器的情况下做到数据的不可逆和不可篡改。

    展开全文
  • 对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。常用的对称加密算法:AES,RC4,3DES传输的示意图如下所示:如上图所示,此种...
  • 非对称加密概述

    万次阅读 多人点赞 2018-08-05 21:13:54
    非对称加密概述 前言 在阅读《精通比特币》的过程中,我发现比特币系统中有两个重要的概念需要利用非对称加密技术: 比特币地址的生成 交易合法性的验证 因此,我用了几天时间学习了密码学基础知识,尤其是非...
  • 最全加密算法对称加密非对称加密

    万次阅读 多人点赞 2016-08-27 10:31:07
    常见加密算法 : DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合;  3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高; RC2和 RC4:用变...
  • 非对称加密算法--RSA加密原理

    万次阅读 2018-12-26 01:29:47
    密码学是在编码与破译的斗争实践中逐步发展起来的,并随着...在中国历史上最早的加密算法的记载出自于周朝兵书《六韬.龙韬》中的《阴符》和《阴书》。在遥远的西方,在希罗多德(Herodotus)的《历史》中记载了公元前...
  • 常见非对称加密算法

    万次阅读 2019-04-10 15:14:35
    对称加密技术只使用一个秘钥不同,对称机密技术使用两个秘钥进行加解密,一个叫做公钥,一个叫做私钥,私钥自己来保管,公钥可以公开,使用公钥加密的数据必须使用私钥解密,反之亦然公钥和私钥是两个不同的秘钥...
  • 三种非对称加密算法总结

    万次阅读 2018-09-06 10:45:14
    最经典的非对称加密算法 也可认为是使用最多的非对称加密算法 能用于密钥分配,也能用于加解密数据(“私钥加密,公钥解密”和“公钥加密,私钥解密”) 密钥长度:512~65536(64的整数倍) 只有发送方有一个...
  • 对称加密算法非对称加密算法

    千次阅读 2019-03-17 16:27:43
    有一种加密算法叫做对称加密对称加密是以前比较常见的一种加密方式。所谓对称加密的意思是说假如有一个人A,他想把一个信号m传递给B,他不能直接将这个信息传递给B,否则会有人可能会窃听。于是通过一些算法,...
  • 非对称加密算法

    千次阅读 2017-01-31 17:08:58
    简述非对称加密算法相比对称加密算法具有高级、双保险的优点,构建密钥对并遵循”公钥加密、私钥解密”和”私钥加密、公钥解密”这两种加密方式,主要有DH(Diffie-Hellman)密钥交换算法、RSA(基于因子分解)、...
  • 数据传输加密  在开发应用过程中,客户端与服务端经常需要进行数据传输,涉及到重要隐私信息时...在这里我主要向大家介绍一下我在开发过程中使用到的加密算法,RSA加密算法+AES加密算法。简单地介绍一下这两种算法吧
  • RSA非对称加密算法详解

    万次阅读 多人点赞 2016-12-11 23:45:30
    加密技术加密技术是对信息进行...3. 不可逆加密对称加密算法 加密过程: 将明文分成N个组,然后对各个组进行加密,形成各自的密文,最后把所有的分组密文进行合并,形成最终的密文。 优点: 算法公开、计算量小、加密
  • 对称加密算法非对称加密算法的区别 1.对称加密算法加密和解密使用的密钥的是相同的,也就是只有一个密钥,而非对称加密算法有两个密钥,也就是加密和解密所使用的密钥是不同的 2.各自算法不同 3.对称加密算法加密...
  • 一、对称加密算法   指加密和解密使用相同密钥的加密算法。对称加密算法用来对敏感数据等信息进行加密,常用的算法包括DES、3DES、AES、DESX、Blowfish、、RC4、RC5、RC6。  DES(Data Encryption Standard):...
  • Java常用非对称加密算法-RSA

    千次阅读 2018-05-15 16:20:07
    RSA作为常用的非对称加密算法,用法基本就是首先生成公钥和私钥密钥对,然后用公钥加密私钥解密或者用私钥加密公钥解密。这里只写代码实现。import javax.crypto.Cipher; import java.security.*; import java....
  • 对称加密算法对称加密:加密和解密使用同一个密钥DES:Data Encryption Standard,56bits3DES:AES:Advanced (128, 192, 256bits)Blowfish,TwofishIDEA,RC6,CAST5特性:1.加密,解密使用同一个密钥,效率高2.将...
  • java 非对称加密算法

    千次阅读 2017-05-23 21:24:36
    慕课网学习笔记 参考:java加密算法 ...非对称加密算法主要有:DH(Diffie-Hellman)密钥交换算法、RSA(基于因子分解)、Elgamal(基于离散对数)、ECC(Elliptical Curve Cryptography,椭圆曲线加密)。DH(密
  • 1、非对称加密过程:  假如现实世界中存在A和B进行通讯,为了实现在安全的通讯通道上实现信息的保密性、完整性、可用性(即信息安全的三个性质),A和B约定使用非对称加密通道进行通讯,具体过程如下:  ...
1 2 3 4 5 ... 20
收藏数 65,976
精华内容 26,390
关键字:

非对称加密算法