Java编程实现非对称加密的方法详解

Java编程实现非对称加密的方法详解

非对称加密算法需要公钥和私钥。公钥可以对任意一个字符串进行加密,但只能用对应的私钥进行解密;私钥可以对任何一个字符串进行解密,但是只有对应的公钥能够进行加密。

生成密钥对

Java提供了多种非对称加密算法,比如RSA算法。使用Java生成RSA密钥对的过程如下:

import java.security.KeyPair;
import java.security.KeyPairGenerator;

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // 初始化密钥长度为2048位
KeyPair keyPair = keyPairGenerator.genKeyPair();

byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();

实例化 KeyPairGenerator 对象可以通过其提供者或者算法名称实现,这里我们使用 RSA 算法,密钥长度为2048位。调用 genKeyPair 方法就可以获得 KeyPair 对象。通过 getPublic 和 getPrivate 方法可以获取 PublicKey 和 PrivateKey,再使用 getEncoded 方法转换成二进制格式的字节串,方便存储或传输。

加密

使用公钥加密一个字符串:

import java.security.PublicKey;
import javax.crypto.Cipher;

String plainText = "Hello, world.";
byte[] publicKeyBytes = ...; // 获取公钥的二进制格式字节串
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));

Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));

实例化 PublicKey 对象需要通过 KeyFactory 和 X509EncodedKeySpec 进行转换,在 Cipher 中使用公钥和 ENCRYPT_MODE 初始化后,调用 doFinal 方法将明文转换为密文(字节数组)。

解密

使用私钥解密上一步所得到的密文:

import java.security.PrivateKey;

byte[] privateKeyBytes = ...; // 获取私钥的二进制格式字节串
PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));

cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
String plainText = new String(decryptedBytes, "UTF-8");

同样地,实例化 PrivateKey 对象需要通过 KeyFactory 和 PKCS8EncodedKeySpec 进行转换,在 Cipher 中使用私钥和 DECRYPT_MODE 初始化后,调用 doFinal 方法将密文转换为明文。

示例说明

示例 1:加密字符串并进行解密

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.Cipher;

public class AsymmetricEncryptionExample {
    public static void main(String[] args) throws Exception {
        String plainText = "Hello, world.";

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048); // 初始化密钥长度为2048位
        KeyPair keyPair = keyPairGenerator.genKeyPair();

        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();

        PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));
        PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));

        Cipher cipher = Cipher.getInstance("RSA");

        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
        System.out.println("Encrypted: " + new String(encryptedBytes, "UTF-8"));

        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        String decryptedText = new String(decryptedBytes, "UTF-8");
        System.out.println("Decrypted: " + decryptedText);
    }
}

输出:

Encrypted: ?0Mf???F???n@G?P?4?p??jd?g?z$?F?5?Xv?

Decrypted: Hello, world.

示例 2:使用公钥加密并传输密文,使用私钥解密

// 发送端
public class AsymmetricEncryptionExample {
    public static void main(String[] args) throws Exception {
        String plainText = "Hello, world.";

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048); // 初始化密钥长度为2048位
        KeyPair keyPair = keyPairGenerator.genKeyPair();

        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();

        PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));

        System.out.println("Encrypted: " + new String(encryptedBytes, "UTF-8"));

        // 假设将 encryptedBytes 转换成Base64编码的字符串,传给接收端
    }
}

// 接收端
public class AsymmetricEncryptionExample {
    public static void main(String[] args) throws Exception {
        byte[] encryptedBytes = ...; // 假设获取到 Base64 编码的密文,解码成字节数组
        byte[] privateKeyBytes = ...; // 获取私钥的二进制格式字节串

        PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        String decryptedText = new String(decryptedBytes, "UTF-8");
        System.out.println("Decrypted: " + decryptedText);
    }
}

输出:

Decrypted: Hello, world.

在示例2中,发送端和接收端都需要获取密钥对中的公钥或私钥。为了简便起见,这里省略了从文件、数据库等外部存储中获取密钥的部分。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java编程实现非对称加密的方法详解 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • java中Calendar类用法实例详解

    Java中Calendar类用法实例详解 什么是Calendar类 Calendar是Java中用于表示日期和时间的类,它提供了一些常用的方法来获取和修改日期和时间信息,同时也支持日期和时间的格式化和解析。 Calendar常用方法 获取日期和时间信息 get(int field):根据给定的日历字段获取其值。 getActualMaximum(int fi…

    Java 2023年5月20日
    00
  • Java多线程Semaphore工具的使用详解

    Java多线程Semaphore工具的使用详解 Semaphore是Java中的一个线程同步工具,可以用于控制线程的并发数,也可以用于多个线程之间的互斥访问。 Semaphore的特性 Semaphore主要有以下特性: 控制并发数:Semaphore可以限制并发线程数,保证同时运行的线程数量不超过Semaphore的指定值。 互斥访问:Semaphore可…

    Java 2023年5月19日
    00
  • java OpenTelemetry日志体系及缺陷解决方案

    Java OpenTelemetry日志体系及缺陷解决方案 什么是OpenTelemetry OpenTelemetry(简称OTel)是一个开放的,可观测性的框架,用于生成、收集,处理和打包跨系统的有关分布式实例的数据。可以帮助开发人员解决微服务监测以及调试等问题。 OpenTelemetry日志体系 OpenTelemetry通过日志(Log)的方式,允…

    Java 2023年5月25日
    00
  • java — IO流

    简介 键盘、内存、硬盘、外接设备等与电脑进行交互的数据这种数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为 输入input 和 输出output ,即流向内存是输入流,流出内存的输出流。Java中I/O操作主要是指使用java.io包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据。 分类 根据数据的流向分为:输…

    Java 2023年4月18日
    00
  • java使用Feign实现声明式Restful风格调用

    Java 的 Feign 库提供了一种声明式的 RESTful 风格的调用方法,可以让我们更加便捷地进行服务调用。下面是使用 Feign 实现声明式 RESTful 风格调用的完整攻略。 什么是 Feign Feign 是 Netflix 开源的一种声明式、模板化的 HTTP 客户端,它的主要作用就是让开发者更加方便的调用 RESTful 风格的 API。 …

    Java 2023年5月31日
    00
  • java多线程volatile内存语义解析

    Java多线程Volatile内存语义解析 什么是Volatile 在Java多线程中,Volatile是一种关键字,用来修饰变量,用于实现多线程之间的可见性和有序性。 当一个变量被声明为Volatile时,Java虚拟机保证每个线程修改了这个变量后,其他线程能够立即看到修改的结果,即保证了可见性。此外,Volatile还会影响指令和执行顺序,保证了有序性。…

    Java 2023年5月19日
    00
  • Springboot-Management的项目实践

    关于“Springboot-Management的项目实践”的完整攻略,我为您提供以下内容: 简介 Springboot-Management是一个基于SpringBoot框架的开源项目,它可以帮助开发者快速构建管理系统,提供了众多易于使用的管理工具,支持多租户、权限控制等功能。 准备工作 在开始使用Springboot-Management之前,需要系统具…

    Java 2023年5月15日
    00
  • ExtJs 实现动态加载grid完整示例

    下面是ExtJs实现动态加载grid完整示例的攻略: 概述 在实际开发中,有时候需要动态加载grid数据,在数据量较大的情况下,提高页面加载速度,减少用户等待时间,这就需要使用ExtJs实现动态加载grid数据。ExtJs中实现动态加载grid数据的方式有两种,一种是使用分页加载数据,另一种是使用滚动加载数据,下面我们将详细介绍这两种方式以及示例。 分页加载…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部