爱生活,爱分享


java加密-05 java实现非对称加密算法

haiten 2019-10-14 598浏览 0条评论
首页/正文
分享到: / / / /

一、非对称加密算法

DH(Diffie-Hellman)密钥交换算法

RSA-基于因子分解(应用范围最广)

ElGamal-基于离散对数

ECC(Elliptical Curve Cryptography)-椭圆曲线加密

非对称加密算法为高级加密算法,提供公钥、私钥双保险。

二、非对称加密算法-DH(密钥交换)

1、理论知识

对称加密带来的困扰:

密钥管理复杂;

密钥传递过程复杂(如何安全地传递密钥成为比较重要的一个环节);

非对称加密算法的起源算法,通过构建本地密钥来解决密钥来解决对称密钥传递的问题,对双方来说密钥是一样的(对称)。

密钥长度 默认 工作模式 填充方式 实现方
512~1024(64倍数) 1024 JDK

2、JDK 实现:

/**
 * java.security.NoSuchAlgorithmException: Unsupported secret key algorithm: DES
 * 由于JDK版本不同,在Java 8 update 161版本以后就会出现此问题,根本原因还是DH密钥长度至少为512位,而DES算法密钥没有这么长,密钥长度不一致引起的。
 * 解决方法:
 * 配置JVM的系统变量:-Djdk.crypto.KeyAgreement.legacyKDF=true
 */
public static void jdkDH() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException {
    String src = "test source";

    // [sender]1、初始化发送方密钥
    KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("DH");
    senderKeyPairGenerator.initialize(512);
    KeyPair senderKeyPair  = senderKeyPairGenerator.generateKeyPair();
    // 发送方公钥,需要把该公钥发送给接收方(网络、文件...)
    byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded();

    // [receiver]2、接收方密钥构建
    // 接收方拿到发送方发送的公钥
    KeyFactory receiverKeyFactory = KeyFactory.getInstance("DH");
    X509EncodedKeySpec receiverX509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKeyEnc);
    PublicKey senderPublicKeyTemp = receiverKeyFactory.generatePublic(receiverX509EncodedKeySpec);
    // 初始化接收方密钥
    DHParameterSpec dhParameterSpec = ((DHPublicKey)senderPublicKeyTemp).getParams();
    KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance("DH");
    receiverKeyPairGenerator.initialize(dhParameterSpec);
    KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair();
    // 接受方公钥,需要把该公钥发送给发送方(网络、文件...)
    byte[] receiverPublicKeyEnc = receiverKeyPair.getPublic().getEncoded();
    // 使用我的密钥和你的公钥生成密钥
    KeyAgreement receiverKeyAgreement = KeyAgreement.getInstance("DH");
    receiverKeyAgreement.init(receiverKeyPair.getPrivate());
    receiverKeyAgreement.doPhase(senderPublicKeyTemp, true);
    SecretKey receiverDESKey = receiverKeyAgreement.generateSecret("DES");


    // [sender]3、发送方密钥构建
    // 发送方拿到接收方返回的公钥
    KeyFactory senderKeyFactory = KeyFactory.getInstance("DH");
    X509EncodedKeySpec senderX509EncodedKeySpec = new X509EncodedKeySpec(receiverPublicKeyEnc);
    PublicKey receiverPublicKeyTemp = senderKeyFactory.generatePublic(senderX509EncodedKeySpec);
    // 使用我的密钥和你的公钥生成密钥
    KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("DH");
    senderKeyAgreement.init(senderKeyPair.getPrivate());
    senderKeyAgreement.doPhase(receiverPublicKeyTemp, true);
    SecretKey senderDESKey = senderKeyAgreement.generateSecret("DES");


    // ////////////////////////////////////////////////////////////////////////////////////////////
    // DH算法的本质是构建本地密钥来解决密钥来解决对称密钥传递的问题
    // 对双方来说密钥是一样的(对称)
    // 对比验证双方各自在本地构建密钥是否一致
    if (Objects.equals(receiverDESKey, senderDESKey)) {
        System.out.println("双方密钥相同");
    }
    // ////////////////////////////////////////////////////////////////////////////////////////////


    // ////////////////////////////////////////////////////////////////////////////////////////////
    // 后续通信采用各自在本地构建的密钥进行对称机密的机制
    // [sender]发送方加密,反之亦然
    Cipher enCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
    enCipher.init(Cipher.ENCRYPT_MODE, senderDESKey);
    byte[] encode = enCipher.doFinal(src.getBytes());
    // Hex 编码
    String encodeHex = Hex.encodeHexString(encode);
    System.out.println(enCipher.getProvider() + "- des encrypt(Hex):" + encodeHex);
    // Base64 编码
    String encodeBase64 = Base64.encodeBase64String(encode);
    System.out.println(enCipher.getProvider() + "- des encrypt(Base64):" + encodeBase64);

    // [receiver]接收方解密,反之亦然
    Cipher deCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
    deCipher.init(Cipher.DECRYPT_MODE, receiverDESKey);
    byte[] decode = deCipher.doFinal(encode);
    // byte[] decode = deCipher.doFinal(Hex.decodeHex(encodeHex));
    // byte[] decode = deCipher.doFinal(Base64.decodeBase64(encodeBase64));
    System.out.println(deCipher.getProvider() + "- des decrypt:" + new String(decode));
    // ////////////////////////////////////////////////////////////////////////////////////////////
}

三、非对称加密算法-RSA

1、理论知识

唯一广泛接受并实现;

数据加密&数字签名;

公钥加密、私钥解密;

私钥加密、公钥解密;

密钥长度 默认 工作模式 填充方式 实现方
512~65536(64倍数) 1024 ECB NoPadding、PKCS1Padding、OAEPWITHMD5AndMGF1Padding、OAEPWITHSHA1AndMGF1Padding、OAEPWITHSHA256AndMGF1Padding、OAEPWITHSHA384AndMGF1Padding、OAEPWITHSHA512AndMGF1Padding JDK
同上 2048 NONE NoPadding、PKCS1Padding、OAEPWITHMD5AndMGF1Padding、OAEPWITHSHA1AndMGF1Padding、OAEPWITHSHA1AndMGF224Padding、OAEPWITHSHA256AndMGF1Padding、OAEPWITHSHA384AndMGF1Padding、OAEPWITHSHA512AndMGF1Padding、ISO9796-1Padding BC

2、JDK 实现:

public static void jdkRSA() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    String src = "test source";

    // 1、初始化密钥
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(512);
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    PublicKey publicKey = keyPair.getPublic();
    PrivateKey privateKey = keyPair.getPrivate();
    System.out.println("Public Key:" + Base64.encodeBase64String(publicKey.getEncoded()));
    System.out.println("Private Key:" + Base64.encodeBase64String(privateKey.getEncoded()));

    // 2、RSA私钥加密、公钥解密——加密
    PKCS8EncodedKeySpec priEnPKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
    KeyFactory priEnKeyFactory = KeyFactory.getInstance("RSA");
    PrivateKey enPrivateKey = priEnKeyFactory.generatePrivate(priEnPKCS8EncodedKeySpec);
    Cipher priEnCipher = Cipher.getInstance("RSA");
    priEnCipher.init(Cipher.ENCRYPT_MODE, enPrivateKey);
    byte[] priEncode = priEnCipher.doFinal(src.getBytes());
    // Hex 编码
    String priEncodeHex = Hex.encodeHexString(priEncode);
    System.out.println(priEnCipher.getProvider() + "- RSA私钥加密、公钥解密——加密(Hex):" + priEncodeHex);
    // Base64 编码
    String priEncodeBase64 = Base64.encodeBase64String(priEncode);
    System.out.println(priEnCipher.getProvider() + "- RSA私钥加密、公钥解密——加密(Base64):" + priEncodeBase64);

    // 3、RSA私钥加密、公钥解密——解密
    X509EncodedKeySpec pubDeX509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
    KeyFactory pubDekeyFactory = KeyFactory.getInstance("RSA");
    PublicKey dePublicKey = pubDekeyFactory.generatePublic(pubDeX509EncodedKeySpec);
    Cipher pubDeCipher = Cipher.getInstance("RSA");
    pubDeCipher.init(Cipher.DECRYPT_MODE, dePublicKey);
    byte[] pubDecode = pubDeCipher.doFinal(priEncode);
    // byte[] pubDecode = deCipher.doFinal(Hex.decodeHex(priEncodeHex));
    // byte[] pubDecode = deCipher.doFinal(Base64.decodeBase64(priEncodeBase64));
    System.out.println(pubDeCipher.getProvider() + "- RSA私钥加密、公钥解密——解密:" + new String(pubDecode));


    // 4、RSA公钥加密、私钥解密——加密
    X509EncodedKeySpec pubEnX509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
    KeyFactory pubEnKeyFactory = KeyFactory.getInstance("RSA");
    PublicKey enPublicKey = pubEnKeyFactory.generatePublic(pubEnX509EncodedKeySpec);
    Cipher pubEnCipher = Cipher.getInstance("RSA");
    pubEnCipher.init(Cipher.ENCRYPT_MODE, enPublicKey);
    byte[] pubEncode = pubEnCipher.doFinal(src.getBytes());
    // Hex 编码
    String pubEncodeHex = Hex.encodeHexString(pubEncode);
    System.out.println(pubEnCipher.getProvider() + "- RSA公钥加密、私钥解密——加密(Hex):" + pubEncodeHex);
    // Base64 编码
    String pubEncodeBase64 = Base64.encodeBase64String(pubEncode);
    System.out.println(pubEnCipher.getProvider() + "- RSA公钥加密、私钥解密——加密(Base64):" + pubEncodeBase64);

    // 5、RSA公钥加密、私钥解密——解密
    PKCS8EncodedKeySpec priDePKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
    KeyFactory priDeKeyFactory = KeyFactory.getInstance("RSA");
    PrivateKey dePrivateKey = priDeKeyFactory.generatePrivate(priDePKCS8EncodedKeySpec);
    Cipher priDeCipher = Cipher.getInstance("RSA");
    priDeCipher.init(Cipher.DECRYPT_MODE, dePrivateKey);
    byte[] priDecode = priDeCipher.doFinal(pubEncode);
    // byte[] priDecode = deCipher.doFinal(Hex.decodeHex(pubEncodeHex));
    // byte[] priDecode = deCipher.doFinal(Base64.decodeBase64(pubEncodeBase64));
    System.out.println(priDeCipher.getProvider() + "- RSA公钥加密、私钥解密——解密:" + new String(priDecode));
}

四、非对称加密算法-ElGamal

1、理论知识

公钥加密算法,不支持私钥加密;

Bouncy Castle 提供实现;

密钥长度 默认 工作模式 填充方式 实现方
160~16384(8倍数) 1024 ECB、NONE NoPadding、PKCS1Padding、OAEPWITHMD5AndMGF1Padding、OAEPWITHSHA1AndMGF1Padding、OAEPWITHSHA224AndMGF1Padding、OAEPWITHSHA256AndMGF1Padding、OAEPWITHSHA384AndMGF1Padding、OAEPWITHSHA512AndMGF1Padding、ISO9796-1Padding BC

2、BC实现:

public static void bcElGamal() throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidAlgorithmParameterException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    String src = "test source";

    // 设置 BC 的提供Provider
    Security.addProvider(new BouncyCastleProvider());

    // 1、初始化密钥
    AlgorithmParameterGenerator 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 publicKey = keyPair.getPublic();
    PrivateKey privateKey = keyPair.getPrivate();
    System.out.println("Public Key:" + Base64.encodeBase64String(publicKey.getEncoded()));
    System.out.println("Private Key:" + Base64.encodeBase64String(privateKey.getEncoded()));

    // 4、ElGamal公钥加密、私钥解密——加密
    X509EncodedKeySpec pubEnX509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
    KeyFactory pubEnKeyFactory = KeyFactory.getInstance("ElGamal");
    PublicKey enPublicKey = pubEnKeyFactory.generatePublic(pubEnX509EncodedKeySpec);
    Cipher pubEnCipher = Cipher.getInstance("ElGamal");
    pubEnCipher.init(Cipher.ENCRYPT_MODE, enPublicKey);
    byte[] pubEncode = pubEnCipher.doFinal(src.getBytes());
    // Hex 编码
    String pubEncodeHex = Hex.encodeHexString(pubEncode);
    System.out.println(pubEnCipher.getProvider() + "- ElGamal公钥加密、私钥解密——加密(Hex):" + pubEncodeHex);
    // Base64 编码
    String pubEncodeBase64 = Base64.encodeBase64String(pubEncode);
    System.out.println(pubEnCipher.getProvider() + "- ElGamal公钥加密、私钥解密——加密(Base64):" + pubEncodeBase64);

    // 5、ElGamal公钥加密、私钥解密——解密
    PKCS8EncodedKeySpec priDePKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
    KeyFactory priDeKeyFactory = KeyFactory.getInstance("ElGamal");
    PrivateKey dePrivateKey = priDeKeyFactory.generatePrivate(priDePKCS8EncodedKeySpec);
    Cipher priDeCipher = Cipher.getInstance("ElGamal");
    priDeCipher.init(Cipher.DECRYPT_MODE, dePrivateKey);
    byte[] priDecode = priDeCipher.doFinal(pubEncode);
    // byte[] priDecode = deCipher.doFinal(Hex.decodeHex(pubEncodeHex));
    // byte[] priDecode = deCipher.doFinal(Base64.decodeBase64(pubEncodeBase64));
    System.out.println(priDeCipher.getProvider() + "- ElGamal公钥加密、私钥解密——解密:" + new String(priDecode));
}

主要知识点来源于慕课慕课网上 moocer老师 提供的 java 加密系列教程。 原创不易,如需转载,请标明出处!

最后修改:2019-10-14 10:33:01 © 著作权归作者所有
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付

上一篇

发表评论

说点什么吧~

评论列表

还没有人评论哦~赶快抢占沙发吧~