Java (1) 将ECDSA转换为专用&;公钥,(2)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中使用ECDSA算法对字符串进行签名。但问题是:

  • 如何将公钥和私钥转换为字符串?(因为我想将它们发送到数据库中)
  • 有人能帮我创建一个简单的教程,介绍如何在java中使用ECDSA算法来验证消息吗?在这一点上,我需要包括签名和公钥作为验证方法
  • 以下是我在java代码中的场景,假设有发送方和接收方:

    • 发送方
    • 接收方
    包裹收件人;
    导入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的机制进行一些额外的研究。这里给出的示例无论如何都很难脱离上下文

    要将密钥存储为字符串,必须首先检索以编码的格式表示密钥的字节数组(注意:编码的未加密)。这可以通过使用class
    key
    中的
    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);
    然后我们可以运行verify
    dsa.verify(message\u hash);
    现在布尔值返回true。谢谢你有用的答案:),请更新你的“verify”答案。对不起,我再也不会这样做了。我是这个“stackoverflow”的新手,谢谢你的警告@ArtjomB。