以下代码示例中
-
先使用java.security包生成EC密钥对(包括R1、K1)
-
之后将该密钥对转换为字符串格式(转换为字符串之后就可以存储到数据库中了)
-
将字符串类型的密钥对数据,反转回密钥对的对象(模拟从数据库取出并转换为对象)
-
使用密钥对中的私钥,对某个数据进行签名
-
使用密钥对中的公钥,对签名后的数据进行验签
-
使用密钥对中的公钥,对数据进行加密
-
使用密钥对中的私钥,对数据进行解密
main函数中包含了整个流程,废话不多说,上代码。
public class KeyPairStrDto {
private String publicKeyStr;
private String privateKeyStr;
public KeyPairStrDto() {
public KeyPairStrDto(String publicKeyStr, String privateKeyStr) {
this.publicKeyStr = publicKeyStr;
this.privateKeyStr = privateKeyStr;
@Override
public String toString() {
return "KeyPairStrDto{" +
"publicKeyStr='" + publicKeyStr + '\'' +
",\n privateKeyStr='" + privateKeyStr + '\'' +
public String getPublicKeyStr() {
return publicKeyStr;
public void setPublicKeyStr(String publicKeyStr) {
this.publicKeyStr = publicKeyStr;
public String getPrivateKeyStr() {
return privateKeyStr;
public void setPrivateKeyStr(String privateKeyStr) {
this.privateKeyStr = privateKeyStr;
import org.apache.commons.codec.binary.Base64;
import sun.misc.BASE64Decoder;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NullCipher;
import java.io.IOException;
import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.*;
public class EcKeyUtils {
public static String R1 = "secp256r1";
public static String K1 = "secp256k1";
* 生成EC密钥对
* @param ecCurveName R1 K1
* @return
public static KeyPairStrDto generatorEcKeyPair(String ecCurveName) {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec(ecCurveName);
keyPairGenerator.initialize(ecGenParameterSpec);
KeyPair ecKeyPair = keyPairGenerator.generateKeyPair();
ECPublicKey ecPublicKey = (ECPublicKey) ecKeyPair.getPublic();
ECPrivateKey ecPrivateKey = (ECPrivateKey) ecKeyPair.getPrivate();
String publicKeyStr = new String(Base64.encodeBase64(ecPublicKey.getEncoded()));
String privateKeyStr = new String(Base64.encodeBase64(ecPrivateKey.getEncoded()));
return new KeyPairStrDto(publicKeyStr, privateKeyStr);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
return null;
* 使用EC密钥对数据进行签名
* @param src 原文数据
* @param priKey 私钥
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws SignatureException
public static String sign(String src, PrivateKey priKey) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature signature = Signature.getInstance("SHA256withECDSA");
byte[] srcData = src.getBytes();
signature.initSign(priKey);
signature.update(srcData);
byte[] signBytes = signature.sign();
return bytesToHex(signBytes);
* @param src 原文
* @param signSrc 签名数据
* @param pubKey 公钥
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws SignatureException
public static Boolean verify(String src, String signSrc, PublicKey pubKey) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
byte[] srcData = src.getBytes();
Signature signatureV = Signature.getInstance("SHA256withECDSA");
signatureV.initVerify(pubKey);
signatureV.update(srcData);
byte[] signBytes = hexToByteArray(signSrc);
return signatureV.verify(signBytes);
* 利用公钥进行对数据进行加密
* @param src
* @param pubKey
* @return
* @throws InvalidAlgorithmParameterException
* @throws InvalidKeyException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
public static String encrypt(String src, ECPublicKey pubKey) throws InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
byte[] srcData = src.getBytes();
ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(pubKey.getW(), pubKey.getParams());
Cipher cipher = new NullCipher();
cipher.init(Cipher.ENCRYPT_MODE, pubKey, ecPublicKeySpec.getParams());
byte[] encBytes = cipher.doFinal(srcData);
return bytesToHex(encBytes);
* 利用私钥对数据进行解密
* @param encStr
* @param priKey
* @return
* @throws InvalidAlgorithmParameterException
* @throws InvalidKeyException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
private static String decrypt(String encStr, ECPrivateKey priKey) throws InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
byte[] encBytes = hexToByteArray(encStr);
ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(priKey.getS(), priKey.getParams());
Cipher cipher = new NullCipher();
cipher.init(Cipher.DECRYPT_MODE, priKey, ecPrivateKeySpec.getParams());
byte[] decBites = cipher.doFinal(encBytes);
return new String(decBites);
* 字符串转公钥
* @param publicKeyString
* @return
public static PublicKey strToPublicKey(String publicKeyString) {
PublicKey publicKey = null;
try {
X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(
new BASE64Decoder().decodeBuffer(publicKeyString));
KeyFactory keyFactory = KeyFactory.getInstance("EC");
publicKey = keyFactory.generatePublic(bobPubKeySpec);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
return publicKey;
* 字符串转私钥
* @param privateKeyString
* @return
public static PrivateKey strToPrivateKey(String privateKeyString) {
PrivateKey privateKey = null;
try {
byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(privateKeyString);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
return privateKey;
* 字节数组转16进制
* @param bytes 需要转换的byte数组
* @return 转换后的Hex字符串
public static String bytesToHex(byte[] bytes) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() < 2) {
sb.append(0);
sb.append(hex);
return sb.toString();
* hex字符串转byte数组
* @param inHex 待转换的Hex字符串
* @return 转换后的byte数组结果
public static byte[] hexToByteArray(String inHex) {
int hexlen = inHex.length();
byte[] result;
if (hexlen % 2 == 1) {
hexlen++;
result = new byte[(hexlen / 2)];
inHex = "0" + inHex;
} else {
result = new byte[(hexlen / 2)];
int j = 0;
for (int i = 0; i < hexlen; i += 2) {
result[j] = hexToByte(inHex.substring(i, i + 2));
return result;
* Hex字符串转byte
* @param inHex 待转换的Hex字符串
* @return 转换后的byte
public static byte hexToByte(String inHex) {
return (byte) Integer.parseInt(inHex, 16);
/*-----------------------------------------------------------------------------------*/
public static void main(String[] args) throws Exception {
forTest(R1);
System.out.println();
forTest(K1);
public static void forTest(String ecCurveName) throws Exception {
System.out.println("1-1 开始生成EC密钥对,椭圆曲线数字签名算法的参数为:" + ecCurveName);
KeyPairStrDto keyPairStrDto = generatorEcKeyPair(ecCurveName);
System.out.println("1-2 密钥对生成完成:" + keyPairStrDto);
String src = "1234567890";
System.out.println("2 原文:" + src);
ECPrivateKey priKey = (ECPrivateKey) strToPrivateKey(keyPairStrDto.getPrivateKeyStr());
String singResult = sign(src, priKey);
System.out.println("3-1 使用EC密钥对中的私钥对数据进行签名:singResult=" + singResult);
ECPublicKey pubKey = (ECPublicKey) strToPublicKey(keyPairStrDto.getPublicKeyStr());
Boolean verifyResult = verify(src, singResult, pubKey);
System.out.println("3-2 验签完成:verifyResult=" + verifyResult);
String encStr = encrypt(src, pubKey);
System.out.println("4-1 使用EC公钥对中的私钥对数据进行加密:encStr=" + encStr);
String decStr = decrypt(encStr, priKey);
System.out.println("4-2 利用私钥对数据进行解密:decStr=" + decStr);
执行结果:
使用docker安装并运行
docker pull autofitcloud/isitfit:latest
docker run -it -v ~/.aws:/root/.aws autofitcloud/isitfit:latest bash # drops within the docker container's terminal
isitfit cost analyze
isitfit cost optimize
Apache许可证2.0。 检查文件
开发人员注意事项
要遵守我们的公告:
首先查看一下 OpenSSL 内建了哪些椭圆曲线,使用命令为:
openssl ecparam -list_curves
选择一条椭圆曲线创建 ECC 公私钥对,这里使用 secp256k1,执行命令:
openssl ecparam -name secp256k1 -genkey -out ec.key
可以用文本编辑器打开 ec.key 文件,其内容类似于:
—–BEGIN EC PARAMETERS—–
BgUrgQQACg==
—–END EC PARAMETERS—–
—–BEGIN EC PRIVATE KEY—–
MHQCAQEEINMie6Xet
import javacard.security.ECKey; //导入方法依赖的package包/类/*** \brief Initialize an EC key with the curve parameters from buf.** \param buf The buffer containing the EC curve parameters. It must be TLV with ...
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
kpg.initialize(new ECGenParameterSpec("secp521r1"), new SecureRandom());
KeyPair keyPair = kpg.generateKeyPair();
ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate();
1. 以太坊账户
以太坊使用非对称密钥进行身份识别。每个账户拥有自己独立的私钥(256位随机数),私钥通过椭圆曲线加密算法得到对应的公钥,再由公钥的后20字节作为账户地址值。私钥用于签名,公钥用于核对信息。得到私钥意味着得到了该账户的全部信息。
2.Web3j中的账户管理
Web3j中账户管理主要由org.web3j.crypto包实现,常用的类有以下三个:
RSA 加密算法是一种非对称加密算法,即 RSA 拥有一对密钥(公钥 和 私钥),公钥可公开。公钥加密的数据,只能由私钥解密;私钥加密的数据只能由公钥解密。RSA 非对称加密在使用中通常公钥公开,私钥保密,使用公钥加密,私钥解密。公钥加密后的数据,只有用私钥才能解,只有服务端才有对应的私钥,因此只有服务端能解密,中途就算数据被截获,没有私钥依然不知道数据的原文内容,因此达到数据安全传输的目的。
拥有众多加密方式:baes64_md5()、base64_hmac_md5(, )、base64_hmac_sha1(, )、base64_hmac_sha256(, )、base64_sha1()、base64_sha256()、hex_hmac_md5(, )、hex_hmac_sha1(, )、hex_hmac_sha256(, )、hex_md5()、hex_sha1()、hex_sha256()、hmac_md5(, )、hmac_sha1(, )、hmac_sha256(, )
简单调用。
在上一篇《Java&keytool生成RSA密钥》中,我们用keytool先生成密钥库和公钥证书,然后通过代码方式获得文件和BASE64串形式的公私密钥对,而其实根本无这么复杂,可直接通过JAVA代码获得公私密钥对。代码如下:package com.bijian.test;import java.io.FileOutputStream;import java.io.ObjectOutput...