ECDSA 字节数组转换为私钥错误
ECDSA byte array into Private Key Error
我想将我的私钥保存在 json 文件(十六进制格式)中,然后将其读取为私钥。
此处Keys生成函数
public void generateKeyPair() {
try {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDSA", "BC");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256k1");
keyGen.initialize(ecSpec,random);
KeyPair keyPair = keyGen.generateKeyPair();
privateKey = keyPair.getPrivate();
publicKey = keyPair.getPublic();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
这就是我将其保存到 json 文件中的方式
a.generateKeyPair();
byte[] enc_key = a.privateKey.getEncoded();
StringBuilder key_builder = new StringBuilder();
for(byte b : enc_key){
key_builder.append(String.format( "%02X",b));
}
String serialized_key = key_builder.toString();
account.privateKey=serialized_key;
try (Writer writer = new FileWriter("Output.json")) {
Gson gson = new GsonBuilder().create();
gson.toJson(account, writer);
} catch (IOException e) {
e.printStackTrace();
}
并从文件中读取
Gson gson = new GsonBuilder().create();
try (Reader read1 = new FileReader("Output.json")) {
account=gson.fromJson(read1,account.getClass());
byte[] encoded_key=account.privateKey.getBytes();
a.privateKey = getPrivateKey(encoded_key);
public static PrivateKey getPrivateKey(byte[] privkey) throws NoSuchAlgorithmException, InvalidKeySpecException {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privkey);
KeyFactory kf = null;
try {
kf = KeyFactory.getInstance("ECDSA", "BC");
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
PrivateKey privateKey = kf.generatePrivate(privateKeySpec);
return privateKey;
}
函数失败,出现错误
java.security.spec.InvalidKeySpecException: encoded key spec not recognized: failed to construct sequence from byte[]: unknown tag 19 encountered
您忘记了对私钥进行十六进制解码。只是执行 getBytes
不会那样做。
编码字节以序列开始,标签0x30
。这在十六进制中当然是 "30"
或者在 ASCII 中:0x33, 0x30
:这些是 getBytes
返回的前两个字节。现在解码器查看位值为 0b001_10011
的第一个字节。最后 5 位编码标记值,即 16 + 2 + 1 = 19。因此出现特定错误。
我想将我的私钥保存在 json 文件(十六进制格式)中,然后将其读取为私钥。
此处Keys生成函数
public void generateKeyPair() {
try {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDSA", "BC");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256k1");
keyGen.initialize(ecSpec,random);
KeyPair keyPair = keyGen.generateKeyPair();
privateKey = keyPair.getPrivate();
publicKey = keyPair.getPublic();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
这就是我将其保存到 json 文件中的方式
a.generateKeyPair();
byte[] enc_key = a.privateKey.getEncoded();
StringBuilder key_builder = new StringBuilder();
for(byte b : enc_key){
key_builder.append(String.format( "%02X",b));
}
String serialized_key = key_builder.toString();
account.privateKey=serialized_key;
try (Writer writer = new FileWriter("Output.json")) {
Gson gson = new GsonBuilder().create();
gson.toJson(account, writer);
} catch (IOException e) {
e.printStackTrace();
}
并从文件中读取
Gson gson = new GsonBuilder().create();
try (Reader read1 = new FileReader("Output.json")) {
account=gson.fromJson(read1,account.getClass());
byte[] encoded_key=account.privateKey.getBytes();
a.privateKey = getPrivateKey(encoded_key);
public static PrivateKey getPrivateKey(byte[] privkey) throws NoSuchAlgorithmException, InvalidKeySpecException {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privkey);
KeyFactory kf = null;
try {
kf = KeyFactory.getInstance("ECDSA", "BC");
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
PrivateKey privateKey = kf.generatePrivate(privateKeySpec);
return privateKey;
}
函数失败,出现错误
java.security.spec.InvalidKeySpecException: encoded key spec not recognized: failed to construct sequence from byte[]: unknown tag 19 encountered
您忘记了对私钥进行十六进制解码。只是执行 getBytes
不会那样做。
编码字节以序列开始,标签0x30
。这在十六进制中当然是 "30"
或者在 ASCII 中:0x33, 0x30
:这些是 getBytes
返回的前两个字节。现在解码器查看位值为 0b001_10011
的第一个字节。最后 5 位编码标记值,即 16 + 2 + 1 = 19。因此出现特定错误。