Java中加密方式之非对称加密

大家好,我是程序员大猩猩。

Java中加密方式之对称加密icon-default.png?t=N7T8http://mp.weixin.qq.com/s?__biz=MzIzODUwMTM0Mg==&mid=2247484107&idx=1&sn=7d84d1e71323cf11547a1705e7ac1118&chksm=e9392e7ade4ea76c957cc5c823db53026163f343a1f05f8c4ba59631069cc8786a8ddf8763a7&scene=21#wechat_redirect

上一篇文章我们说了Java的对称加密概念以及我们经常使用的对称加密方式和代码示例,今天我们来说一说非对称加密。

非对称加密相比较对称加密,它是采用的一对密钥来实现加密的,一对密钥包含公钥与私钥,公钥可以公开,私钥我们需要进行保密保管,因为私钥不需要分发。

Java中java.security包下提供非对称加密。

有人说为什么有了对称加密,为什么还要有个非对称加密,那么首先我们来说说这俩种加密的优缺点。

对称加密:

优点:对称加密算法通常比非对称加密算法更快,更适合加密大量数据。

缺点:因为同一个密钥需要用于加密和解密,所以密钥的安全分发和存储是个至关重要的问题。如果密钥泄露,加密的数据就会被轻易解密。

非对称加密:

优点:如我们上方所说非对称加密采用一对密钥来加密,可以大大增强数据的完整性和真实性,而且,非对称加密还可以用于数字签名。

缺点:非对称加密算法相对来说没有对称加密快速,所以它不适合加密大量数据。此外,如果私钥你不小心丢了,那么加密的数据,怎么解密都没有办法解密。

说了这么多,了解了俩种加密方式,我们来了解一下,非对称加密有哪几种常见的加密方式。

一、RSA

RSA称为Rivest-Shamir-Adleman是一种非对称加密算法,广泛用于数据传输、数字签名和密钥交换。在Java中,RSA算法可以通过java.security包中的KeyPairGenerator和Cipher类来实现。

import javax.crypto.Cipher;
import java.security.*;
import java.util.Base64;

public class RSAEncryptionDemo {
    public static void main(String[] args) throws Exception {
        // 创建RSA密钥对生成器
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        // 获取公钥和私钥
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        // 创建RSA加密对象
        Cipher cipher = Cipher.getInstance("RSA");

        // 加密数据
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        String originalText = "Hello, World!";
        byte[] encryptedBytes = cipher.doFinal(originalText.getBytes());
        String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
        System.out.println("加密后: " + encryptedText);

        // 解密数据
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
        String decryptedText = new String(decryptedBytes);
        System.out.println("解密后: " + decryptedText);
    }
}

运行结果

加密后: aaMWUd65otrubkskidn3yhpLb9H1gbXi836X8eGJKxqWbJypNZRFi0cgTvpynqdu1wSRJoPtRys9bQDA9OvfHfQ98ZUUpa1NMhl8ptNyl0wMZwQiUrUg5qh/ekRmZseTPcz6nQYIhmYYkRhof7Le/S2Qx6kCmOX+m1LpjagDrVV9rOj2QkaOje5ugd7YxDLGa25e++aWKYZFFAU4QVYeO8avkUCCQ93xff9xYD20ecjkHgW8Brox6NzB62edxC3UJEbAkadU51t0J7h+qeVee+r2djg7hDQyTB0XKjSo1ub+BHbjxADv/SlkVZ+rLcEY1jzoAL+VZQ4cPK+//IBPSg==
解密后: Hello, World!

通过代码示例,我们可以看到使用KeyPairGenerator生成一个RSA密钥对。然后,我们使用Cipher对象来加密和解密文本数据。加密后的数据被转换为Base64编码的字符串,以便于打印和传输。

二、DSA (Digital Signature Algorithm)

DSA,它基于椭圆曲线密码学和整数因子分解的困难性。DSA可以用于验证数据的完整性和真实性。在Java中,DSA算法可以通过java.security包中的KeyPairGenerator、Signature和其他相关类来实现

import java.security.*;
import java.util.Base64;

public class DSADemo {
    public static void main(String[] args) throws Exception {
        // 创建DSA密钥对生成器
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        // 获取公钥和私钥
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        // 创建DSA签名对象
        Signature signature = Signature.getInstance("SHA256withDSA");

        // 签署数据
        signature.initSign(privateKey);
        String data = "Hello, World!";
        signature.update(data.getBytes());
        byte[] sign = signature.sign();
        String signedData = Base64.getEncoder().encodeToString(sign);
        System.out.println("加密后: " + signedData);

        // 验证签名
        signature.initVerify(publicKey);
        signature.update(data.getBytes());
        boolean isValid = signature.verify(Base64.getDecoder().decode(signedData));
        System.out.println("解密后是否正确: " + isValid);
    }
}

运行结果

加密后: MDwCHG0RYpNu4n26fSjUPpPpIVmimgCR1oxp4XO2ndYCHATQ7ZvUqQImU2uPCRdB8zTG444ZFqG7T0/Q9Wo=
解密后: true

看示例中,我们首先使用KeyPairGenerator生成一个DSA密钥对。然后,我们使用Signature对象来创建数字签名并验证签名。签名和验证过程中,我们使用了SHA-256消息摘要算法与DSA结合使用。

三、ECC (Elliptic Curve Cryptography)

ECC提供了与RSA和其他传统非对称算法相比更高的安全性,同时可以使用更短的密钥。ECC在安全性、处理速度和存储需求方面都非常有优势,特别是在移动设备和嵌入式设备中。在Java中,ECC可以通过java.security包中的KeyPairGenerator、KeyFactory、Signature和其他相关类来实现。

我们来看下示例:

import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;

public class ECCDemo {
    public static void main(String[] args) throws Exception {
        // 创建ECC密钥对生成器
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
        // 使用secp256r1曲线
        keyPairGenerator.initialize(new ECGenParameterSpec("secp256r1"));
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        // 获取公钥和私钥
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        // 创建ECC签名对象
        Signature signature = Signature.getInstance("SHA256withECDSA");

        // 签署数据
        signature.initSign(privateKey);
        String data = "Hello, World!";
        signature.update(data.getBytes());
        byte[] sign = signature.sign();
        String signedData = Base64.getEncoder().encodeToString(sign);
        System.out.println("签名数据: " + signedData);

        // 验证签名
        signature.initVerify(publicKey);
        signature.update(data.getBytes());
        boolean isValid = signature.verify(Base64.getDecoder().decode(signedData));
        System.out.println("解签是否正确: " + isValid);
    }
}

运行结果

签名数据: MEUCIQC6l89xlLGg5ad1wZgao5+SoYzkYvbWTK1LNzBihXp/TwIgWjc3xv4Asi+gJ8C6MkyYxUnAP+rPdSOxRXF56RRVepQ=
解签是否正确: true

示例中,我们首先使用KeyPairGenerator和ECGenParameterSpec生成一个ECC密钥对。然后,我们使用Signature对象来创建数字签名并验证签名。签名和验证过程中,我们使用了SHA-256消息摘要算法与ECDSA结合使用。

请注意,ECC算法仅用于创建和验证数字签名,它不适用于数据加密。如果需要加密数据,应该使用对称加密或非对称加密算法。此外,ECC的安全性取决于所使用的椭圆曲线和实现的细节。

四、Diffie-Hellman

Diffie-Hellman密钥交换协议是一种方法,允许两个用户在不安全的通道上安全地交换密钥。它是由Whitfield Diffie和Martin Hellman在1976年发明的,是第一个公开披露的密钥交换协议,它奠定了现代加密通信的基础。在Java中,Diffie-Hellman密钥交换可以通过java.security包中的KeyPairGenerator、KeyAgreement和其他相关类来实现。

import javax.crypto.KeyAgreement;
import javax.crypto.spec.DHParameterSpec;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.Base64;

public class DiffieHellmanDemo {
    public static void main(String[] args) throws Exception {
        // 生成Diffie-Hellman参数
        AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator.getInstance("DH");
        paramGen.init(2048);
        AlgorithmParameters params = paramGen.generateParameters();
        DHParameterSpec dhParams = params.getParameterSpec(DHParameterSpec.class);

        // 生成Alice的密钥对
        KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");
        aliceKpairGen.initialize(dhParams);
        KeyPair aliceKpair = aliceKpairGen.generateKeyPair();

        // 生成Bob的密钥对
        KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
        bobKpairGen.initialize(dhParams);
        KeyPair bobKpair = bobKpairGen.generateKeyPair();

        // Alice的密钥交换
        KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
        aliceKeyAgree.init(aliceKpair.getPrivate());
        aliceKeyAgree.doPhase(bobKpair.getPublic(), true);

        // Bob的密钥交换
        KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
        bobKeyAgree.init(bobKpair.getPrivate());
        bobKeyAgree.doPhase(aliceKpair.getPublic(), true);

        // 生成共享密钥
        byte[] aliceSharedSecret = aliceKeyAgree.generateSecret();
        byte[] bobSharedSecret = bobKeyAgree.generateSecret();

        // 输出共享密钥
        String aliceKey = Base64.getEncoder().encodeToString(aliceSharedSecret);
        System.out.println("Alice's的共享密钥: " + aliceKey);
        String bobKey = Base64.getEncoder().encodeToString(bobSharedSecret);
        System.out.println("Bob's  的共享密钥: " + bobKey);
        System.out.println("密钥是否相同: " + bobKey.equals(aliceKey));
    }
}

运行结果

Alice's的共享密钥: sW3xY/Vqn+fBuv4PRKWozaK+V66I4jKvEa8qCcmz/6vEx6a4pk2jzVsFVNRfoCx7mYGbEqBYz1YJSCCNZOuG1VApeN43Cp5YiFr3BcUZQF+51fZf9IYopOxLWeA68J3dKx9SdSgYRkhEI4zWJC+RS6jaf5ElFT/duzVxCrzYbabptvcWsxHhi40TvBcDHpUCbO4OXeYiDgUPuOJYfJTeZrwybVppOqgQH46JIw6EBnu8jWXFX14XuncgIqCdDrA/Etp2G7aKX+7nsow5zPKI+dzw1CN9kSzWUuy4GiCT4AEqvgOUecg5qMfSGLzu4CNacIkBFtAaM5gXrFr2m1gsXg==
Bob's  的共享密钥: sW3xY/Vqn+fBuv4PRKWozaK+V66I4jKvEa8qCcmz/6vEx6a4pk2jzVsFVNRfoCx7mYGbEqBYz1YJSCCNZOuG1VApeN43Cp5YiFr3BcUZQF+51fZf9IYopOxLWeA68J3dKx9SdSgYRkhEI4zWJC+RS6jaf5ElFT/duzVxCrzYbabptvcWsxHhi40TvBcDHpUCbO4OXeYiDgUPuOJYfJTeZrwybVppOqgQH46JIw6EBnu8jWXFX14XuncgIqCdDrA/Etp2G7aKX+7nsow5zPKI+dzw1CN9kSzWUuy4GiCT4AEqvgOUecg5qMfSGLzu4CNacIkBFtAaM5gXrFr2m1gsXg==
密钥是否相同: true

示例中,我们首先使用AlgorithmParameterGenerator生成Diffie-Hellman参数。然后,我们为Alice和Bob生成各自的密钥对。接着,我们使用KeyAgreement对象来执行密钥交换,最终生成共享密钥。

请注意,Diffie-Hellman密钥交换协议仅用于交换密钥,它不直接用于加密或解密数据。交换得到的共享密钥通常用作对称加密算法的密钥,用于加密实际传输的数据。

  • 26
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员大猩猩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值