Java基于SunEC的ECDH secp256r1密钥对实现字符串加解密
实现方案说明
椭圆曲线(EC)算法本身不提供原生的加解密能力,仅支持密钥协商(ECDH)、数字签名(ECDSA)两类操作,因此直接搜索EC加解密很难找到可直接运行的实现。要实现公钥加密、私钥解密的需求,直接使用标准的**ECIES(椭圆曲线集成加密方案)**即可,这是基于EC密钥的标准化混合加密协议,JDK内置的SunJCE安全提供者原生支持该算法,不需要引入任何第三方依赖,和当前生成的secp256r1类型EC密钥对完全兼容。
ECIES内部会自动通过ECDH协商出对称密钥,再用AES-GCM认证加密算法完成实际的数据加解密,不需要自行实现密钥协商和对称加密的组合逻辑,避免手动拼接逻辑引入安全漏洞。
完整代码实现
两个方法的实现如下,密文统一使用Base64编码为字符串,方便存储和传输:
import java.security.*; import java.security.spec.ECGenParameterSpec; import javax.crypto.Cipher; import java.util.Base64; import java.nio.charset.StandardCharsets; public class EcCryptoUtil { /** * 公钥加密字符串 * @param publicKey EC公钥 * @param stringToEncrypt 待加密明文 * @return Base64编码的密文 */ public String encryptString(PublicKey publicKey, String stringToEncrypt) throws GeneralSecurityException { Cipher cipher = Cipher.getInstance("ECIES"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] cipherBytes = cipher.doFinal(stringToEncrypt.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(cipherBytes); } /** * 私钥解密字符串 * @param privateKey EC私钥 * @param stringToDecrypt Base64编码的密文 * @return 解密后的明文 */ public String decryptString(PrivateKey privateKey, String stringToDecrypt) throws GeneralSecurityException { Cipher cipher = Cipher.getInstance("ECIES"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] plainBytes = cipher.doFinal(Base64.getDecoder().decode(stringToDecrypt)); return new String(plainBytes, StandardCharsets.UTF_8); } }
使用示例
和现有密钥生成逻辑的衔接代码如下,可直接运行验证:
public class Main { public static void main(String[] args) throws GeneralSecurityException { // 原有生成密钥对的逻辑,不需要做任何修改 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "SunEC"); ECGenParameterSpec ecParameterSpec = new ECGenParameterSpec("secp256r1"); keyPairGenerator.initialize(ecParameterSpec); KeyPair ecdhKeyPair = keyPairGenerator.genKeyPair(); PrivateKey privateKey = ecdhKeyPair.getPrivate(); PublicKey publicKey = ecdhKeyPair.getPublic(); // 加解密测试 EcCryptoUtil cryptoUtil = new EcCryptoUtil(); String plainText = "测试EC加密的字符串内容123!@#"; String cipherText = cryptoUtil.encryptString(publicKey, plainText); String decryptText = cryptoUtil.decryptString(privateKey, cipherText); System.out.println("明文:" + plainText); System.out.println("密文:" + cipherText); System.out.println("解密结果:" + decryptText); System.out.println("加解密结果一致:" + plainText.equals(decryptText)); } }
注意事项
- 该实现兼容OpenJDK/Oracle JDK 8及以上所有版本,不需要额外引入BouncyCastle等第三方加密库
- 不要自行实现ECDH协商密钥+手动拼接AES加密的逻辑,非专业实现很容易引入重放攻击、密钥派生错误等安全问题,直接使用标准ECIES实现即可
- 密文始终使用Base64编码传输,不要直接把原始密文字节转成字符串,会出现编码错误导致解密失败
内容的提问来源于stack exchange,提问作者Jason Chan
相关产品推荐
相关产品推荐

