Java (1) 将ECDSA转换为专用&;公钥,(2)ECDSA验证
接下来是一个简单的教程,介绍如何在不使用任何第三方库的情况下,在java中使用ECDSA算法对字符串进行签名。但问题是:Java (1) 将ECDSA转换为专用&;公钥,(2)ECDSA验证,java,cryptography,digital-signature,jce,ecdsa,Java,Cryptography,Digital Signature,Jce,Ecdsa,接下来是一个简单的教程,介绍如何在不使用任何第三方库的情况下,在java中使用ECDSA算法对字符串进行签名。但问题是: 如何将公钥和私钥转换为字符串?(因为我想将它们发送到数据库中) 有人能帮我创建一个简单的教程,介绍如何在java中使用ECDSA算法来验证消息吗?在这一点上,我需要包括签名和公钥作为验证方法 以下是我在java代码中的场景,假设有发送方和接收方: 发送方 接收方 包裹收件人; 导入java.math.biginger; 导入java.security.KeyPair;
- 发送方
- 接收方
包裹收件人;
导入java.math.biginger;
导入java.security.KeyPair;
导入java.security.KeyPairGenerator;
导入java.security.PrivateKey;
导入java.security.PublicKey;
导入java.security.SecureRandom;
导入java.security.Signature;
公共类验证{
公共静态void main(字符串[]args)引发异常{
/*
第一步,从数据库中获取公钥。
第二步,接收消息+签名。
第三步,将消息和签名拆分为消息的“数组[0]”,
和“签名的数组[1]”
验证签名您在处理ECDSA时问了很多不同的问题。我将在这里回答您关于数据库存储的第一个问题。如果您想了解如何正确使用ECDSA,我建议您对ECDSA的机制进行一些额外的研究。这里给出的示例无论如何都很难脱离上下文
要将密钥存储为字符串,必须首先检索以编码的格式表示密钥的字节数组(注意:编码的未加密)。这可以通过使用classkey
中的getEncoded()
方法来完成,该方法是公钥和私钥的上接口
例如:
PrivateKey key = // ...
byte[] enc_key = key.getEncoded();
// Byte array to string
StringBuilder key_builder = new StringBuilder();
for(byte b : enc_key){
key_builder.append(String.format("%02x", b));
}
String serialized_key = key_builder.toString();
String serialzed_key = // ...
byte[] encoded_key = // serialzed_key -> byte array conversion
// If key is private, use PKCS #8
PKCS8EncodedKeySpec formatted_private = new PKCS8EncodedKeySpec(encoded_key);
// or, if key is public, use X.509
X509EncodedKeySpec formatted_public = new X509EncodedKeySpec(encoded_key);
// Retrieve key using KeyFactory
KeyFactory kf = KeyFactory.getInstance("EC");
PublicKey pub = kf.generatePublic(formatted_public);
PrivateKey priv = kf.generatePrivate(formatted_private);
要再次从数据库加载密钥,需要将字符串解析为字节数组,将其传递到相应的密钥规范中,然后使用密钥工厂检索它
例如:
PrivateKey key = // ...
byte[] enc_key = key.getEncoded();
// Byte array to string
StringBuilder key_builder = new StringBuilder();
for(byte b : enc_key){
key_builder.append(String.format("%02x", b));
}
String serialized_key = key_builder.toString();
String serialzed_key = // ...
byte[] encoded_key = // serialzed_key -> byte array conversion
// If key is private, use PKCS #8
PKCS8EncodedKeySpec formatted_private = new PKCS8EncodedKeySpec(encoded_key);
// or, if key is public, use X.509
X509EncodedKeySpec formatted_public = new X509EncodedKeySpec(encoded_key);
// Retrieve key using KeyFactory
KeyFactory kf = KeyFactory.getInstance("EC");
PublicKey pub = kf.generatePublic(formatted_public);
PrivateKey priv = kf.generatePrivate(formatted_private);
如果您只想将ECDSA用作签名算法,则验证与使用verify
方法而不是sign
方法进行签名相同,如下所示:
byte[] message_hash = // ...
byte[] candidate_message = // ...
PublicKey pub = // ...
Signature dsa = Signature.getInstance("SHA1withECDSA");
dsa.initVerify(pub);
dsa.update(candidate_message);
boolean success = dsa.verify(message_hash);
谢谢你的回答,在这一点上有点错误:)for(byte b:enc_key){key_builder.append(String.format(“%02x”);}
在像这样追加字符串时,你可能忘了放“b”:for(byte b:enc_key){key_builder.append(String.format(“%02x”,b));}
现在我要讨论验证问题。@anIndonesian Oops,愚蠢的我。在答案中修复了它。那么你只使用ECDSA进行签名验证?如果是这样,它与签名的过程完全相同,只是你使用方法initVerify()
和verify()
而不是initSign()
和sign()
。当我试图解析公钥和私钥时出错,我想保持此线程干净,直到我编辑到一个已解决的问题为止。如果我使用外部链接,我会将带有错误信息的代码粘贴到抱歉:)哇,另一种方法如何将公钥和私钥解析为“字节数组”,我使用的是bouncy castle lib:)将字节[]enc_key=key.getEncoded();
以String keyString=new String(Base64.encode(enc_key));
结束,然后将“keyString”发送到数据库中,用Base64.decode(keyString)加载密钥
然后格式化这两个密钥,它就可以工作了。现在我真的要去验证代码了。谢谢terminator。很抱歉,验证消息时你又出现了一个小错误:)我们必须用原始消息运行更新方法,因为ori_消息在验证过程之前处于空状态,代码类似于byte[]ori\u message=\\…
dsa.update(ori\u message);
然后我们可以运行verifydsa.verify(message\u hash);
现在布尔值返回true。谢谢你有用的答案:),请更新你的“verify”答案。对不起,我再也不会这样做了。我是这个“stackoverflow”的新手,谢谢你的警告@ArtjomB。