网络安全-非对称加密

192 阅读6分钟
  1. 什么是非对称加密

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

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

  1. 常见的非对称加密算法
  • RSA算法:

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

  • DSA算法

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

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

  • ECC算法

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

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

  • DH算法

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

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

  1. RSA算法的JAVA实现
public class RSAUtil {
    public static Map<String, String> initKeyPair(){
        try {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
            kpg.initialize(1024);
            KeyPair keyPair = kpg.generateKeyPair();
            PublicKey aPublic = keyPair.getPublic();
            PrivateKey aPrivate = keyPair.getPrivate();
            String publicKey = Base64Utils.encodeToString(aPublic.getEncoded());
            String privateKey = Base64Utils.encodeToString(aPrivate.getEncoded());
            Map<String, String> keyMap = new HashMap<>();
            keyMap.put("publicKey", publicKey);
            keyMap.put("privateKey", privateKey);
            return keyMap;
        }catch (Exception ex){
            ex.printStackTrace();
            return null;
        }
    }

    public static String encrypt(String plainText, String key){
        try {
            PublicKey publicKey = KeyFactory.getInstance("RSA")
                    .generatePublic(new X509EncodedKeySpec(Base64Utils.decodeFromString(key)));
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] bytes = cipher.doFinal(plainText.getBytes());
            return Base64Utils.encodeToString(bytes);
        }catch (Exception ex){
            ex.printStackTrace();
            return null;
        }
    }

    public static String decrypt(String cipherText, String key){
        try{
            PrivateKey privateKey = KeyFactory.getInstance("RSA")
                    .generatePrivate(new PKCS8EncodedKeySpec(Base64Utils.decodeFromString(key)));
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] bytes = cipher.doFinal(Base64Utils.decodeFromString(cipherText));
            return new String(bytes);
        }catch (Exception ex){
            ex.printStackTrace();
            return null;
        }
    }

    public static String sign(String str, String key){
        try{
            PrivateKey privateKey = KeyFactory.getInstance("RSA")
                    .generatePrivate(new PKCS8EncodedKeySpec(Base64Utils.decodeFromString(key)));
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(privateKey);
            signature.update(str.getBytes());
            return Base64Utils.encodeToString(signature.sign());
        }catch (Exception ex){
            ex.printStackTrace();
            return null;
        }
    }

    public static boolean verify(String str, String key, String sign){
        try{
            PublicKey publicKey = KeyFactory.getInstance("RSA")
                    .generatePublic(new X509EncodedKeySpec(Base64Utils.decodeFromString(key)));
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initVerify(publicKey);
            signature.update(str.getBytes());
            return signature.verify(Base64Utils.decodeFromString(sign));
        }catch (Exception ex){
            ex.printStackTrace();
            return false;
        }
    }

    public static void main(String[] args) {
        Map<String, String> keyPair = RSAUtil.initKeyPair();
        System.out.println("publicKey: " + keyPair.get("publicKey"));
        System.out.println("privateKey: " + keyPair.get("privateKey"));
        String plainText = "hello world";
        String cipherText = RSAUtil.encrypt(plainText, keyPair.get("publicKey"));
        System.out.println("cipherText: " + cipherText);
        String decryptText = RSAUtil.decrypt(cipherText, keyPair.get("privateKey"));
        System.out.println("decryptText: " + decryptText);
        String sign = RSAUtil.sign(plainText, keyPair.get("privateKey"));
        System.out.println("sign: " + sign);
        boolean verify = RSAUtil.verify(plainText, keyPair.get("publicKey"), sign);
        System.out.println("verify: " + verify);
    }
}

输出: publicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKcpnfBJNdxdEOIbFDJG/LiIQvWmZyqwK/3uyAMFr7lBmMve6NTVhiCG+rrKQK4SkASDsUkVGqyl9NdreusP4xSPin7YFtuB9qiwUoBt9Mr6G1PCdFkHU41AGbUh8r+/NbjjEgeeDUHAfX2VKwTFITpsjfDxh0ykehePkPXKlrmwIDAQAB

privateKey: MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMpymd8Ek13F0Q4hsUMkb8uIhC9aZnKrAr/e7IAwWvuUGYy97o1NWGIIb6uspArhKQBIOxSRUarKX012t66w/jFI+KftgW24H2qLBSgG30yvobU8J0WQdTjUAZtSHyv781uOMSB54NQcB9fZUrBMUhOmyN8PGHTKR6F4+Q9cqWubAgMBAAECgYEAp4EU4Vr216LCK5AjC+vM+Dm3LTr+AyiNuNWpFxNrZDcQwMux4oY5d7uFMiVBAaN0+j/JamYmjUquefidWFQnrIRzqtCam9EJx5neRjCmhx1O+FRCpIdHRPNGR97tMEB+hj1RUm6+YxZaZk7oJNLe4Po5/ypbQXaPyZg8E+4xm+kCQQDwCpp8yLJG22ZoTzg4er4XfOyC0tpQFvbzzlGEfGVh/mjiq8dofl4pFCicobSEF1VI0dC3sFy8xpvDjpWiXsidAkEA1+grNclX+dRJ/X2IqlWojmYk705OYLQpLC4eN6Wtq8Gd837kA24TS0fi6swrMOlBA0EqX5we+YXzSqol1UBDlwJBALi5UD3rLNa+jMaFAFzmiFcG+fOLVBoCMjVZdv4fxN1urUSSsThG1yuBqecvwf1M/4K0hIx3mkZkCQarOZfknTkCQCfh4Sl8Wd3yUwCaUcZ1MD+tqqDx7BR88yYQFtDcr+oMR+sUw3XGvZWoX8hTkp7kV3gMb5Fdu3MIRVrDd12fE10CQQCtteQKyKnawfsTah2XV2syzdu+0Lpm+4qG6KSPXZ4kIGfeh/XES3vcjxTZSZqqLhUoAObDE45/65ek9SOkFF/P

cipherText: Zhm3QbT1Szp/Ca2wvPYiadoTOOt4HSiiGzHODVzsLEYVxSUusYCGx1plMzTUmo1FpyT5I0gjnCQDK9xj0hwVFS89FG+UE0rFIaLHlwqjdSxZ7MrFhC1minTTjHd3pusVBTNgKmyif2y935lM7b4yZIFxzRQcWwqk1lZdgh4lBow=

decryptText: hello world

sign: vcjrtvvGi98Qv2P4khsHxGp8AENK3cdPyOUWyUI3Me400FERIh0Bg9Ps1tfNasbSAVN8ZZgPJa3KIReDVdj/5Q57Yyulpo83XjeP8uSoQ3+axWBi53sKezN0wZxnayTgkbW6Caox9w6TFaPetD+62d6k2F0EAueOgUk87mXHnjk=

verify: true

  1. openssl工具生成rsa密钥并对文件进行加解密

生成私钥: openssl genrsa -out private.pem

生成公钥: openssl rsa -in private.pem -out public.pem -pubout

公钥加密: openssl pkeyutl -encrypt -in hello.txt -inkey public.pem -pubin -out hello.en

私钥解密: openssl pkeyutl -decrypt -in hello.en -inkey private.pem -out hello.de

私钥签名: openssl dgst -sha256 -sign private.pem -out sign.txt hello.txt

公钥验签: openssl dgst -verify public.pem -sha256 -signature sign.txt hello.txt Verified OK