(1)转换ECDSA私人&公钥,(2)ECDSA验证

时间:2014-12-29 02:14:11

标签: java cryptography digital-signature jce ecdsa

discussion之后,这是一个简单的教程,如何在不使用任何第三方库的情况下使用Java中的ECDSA算法来签名字符串。但问题是:

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

    • 发件人方
    package sender;
    import java.math.BigInteger;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.SecureRandom;
    import java.security.Signature;
    public class Sign {    
      public static void main(String[] args) throws Exception {
          /*
           * Generate a key pair
           */
          KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
          SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
    
          keyGen.initialize(256, random);
    
          KeyPair pair = keyGen.generateKeyPair();
    
          /*
          Generate the private and the public key
          */
    
          PrivateKey priv = pair.getPrivate();
          /*
          *and then Convert the priv key into a String;
          *HOW can i do that ? this what i'm asking
          */
    
          PublicKey pub = pair.getPublic();
          /*
          Convert the pub key into a String;
          HOW can i do that ? this what i'm asking
          */      
    
          /*
          -------Encrypt the pub and the priv key, i do with my own code  
          -------Store the enrypted pub & priv key into the database
          -------I'm doing this with my own code
          */
    
    
          /*
          * Create a Signature object and initialize it with the private key
          */
          Signature dsa = Signature.getInstance("SHA1withECDSA");
    
          dsa.initSign(priv);
    
          String str = "This is string to sign";
          byte[] strByte = str.getBytes("UTF-8");
          dsa.update(strByte);
    
          /*
          * Now that all the data to be signed has been read in, generate a
          * signature for it
          */
    
          byte[] realSig = dsa.sign();
          System.out.println("Signature: " + 
                 new BigInteger(1, realSig).toString(16));
          /*
          and Then i'm storing this signature into my database. 
          i have done with this
          */
        }
    }
    
    • 收件人方
    package recipient;
    import java.math.BigInteger;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.SecureRandom;
    import java.security.Signature;
     public class Verify {   
       public static void main(String[] args) throws Exception {
       /*
       Step one, taking public key from the database.
       Step two, receive the message + signature.
       Step three, split the message and signature into an "array[0]" for message,
       and "array[1] for the signature"
    
       Verify the signature <--- Here's what im asking to anybody, 
       how can i do, i mean the sample code ? 
       */  
       }
    }
    

    抱歉我的英文不好:D

1 个答案:

答案 0 :(得分:2)

您在处理ECDSA方面提出了很多不同的问题。我将在这里解决您关于数据库存储的第一个问题。如果您想了解如何正确使用它,我建议您对ECDSA的机制进行一些额外的研究。这里给出的例子无论如何都很难脱离背景。

要将键存储为字符串,必须首先检索表示编码格式的键的字节数组(注意:编码未加密)。这可以通过使用类getEncoded()中的Key方法来完成,该方法是PublicKey和PrivateKey的超接口。

示例:

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);