2

Following this discussion it's a simple tutorial how to sign a string by using ECDSA algorithm in java without using any third-party libraries. But the question is:

  1. How can i convert the public and the private key into a string ? (Because i want to send them into a database).
  2. Can somebody help me create a simple tutorial of how to verify the message by using ECDSA algorithm in java ? at this point i need to include the signature and public key as the verification method.

Here's my scenario in my java code, assume that there's a sender side and the recipient side:

  • Sender side
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
      */
    }
}
  • Recipient side
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 ? 
   */  
   }
}

Sorry for my bad English :D

Community
  • 1
  • 1
Rhony
  • 86
  • 1
  • 10
  • Sorry, im gonna never do that again. Im new in this "stackoverflow", thanks for your warning @ArtjomB. – Rhony Jan 13 '15 at 16:29

1 Answers1

5

You're asking a lot of different questions about dealing with ECDSA. I will address your first question about database storage here. I recommend you do some additional research on the mechanics of ECDSA if you want to learn about how to properly use it. Examples given here would be hard to follow out of context anyway.

To store keys as a string, you must first retrieve the byte array representing the key in its encoded format (note: encoded not encrypted). This can be done by using the getEncoded() method from class Key which is the superinterface of both PublicKey and PrivateKey.

Example:

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

To load the key again from a database you parse the string to a byte array, pass it into the appropriate key specification and then retrieve it by using a key factory.

Example:

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

If all you mean to do is to use ECDSA as a signature algorithm, verification is identical to signing using using the verify methods instead of the sign methods, as follows:

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);
initramfs
  • 8,275
  • 2
  • 36
  • 58
  • Thanks for the answer, little false at this point :) `for(byte b : enc_key){ key_builder.append(String.format("%02x")); }` you may forget to put the "b" while append the string like this one: `for(byte b : enc_key){ key_builder.append(String.format("%02x", b)); }` Now im going to the verification problem. – Rhony Dec 29 '14 at 09:20
  • @anIndonesian Oops, silly me. Fixed it in the answer. So you're using ECDSA for signature verification only? If so, its the exact same process as signing just you use the method `initVerify()` and `verify()` instead of `initSign()` and `sign()`. – initramfs Dec 29 '14 at 10:41
  • I got error when i try to parse against the public and the private key, wanna keeping clean this thread until i edit to a SOLVED problem i paste the code with the error information at [Load private & public key](http://pastebin.com/rb9itk7h) Sorry if i'm using external link :) – Rhony Dec 29 '14 at 11:39
  • Whoa, another way how to parse both the public and the private key into "byte array", i'm using bouncy castle lib :) convert the `byte[] enc_key = key.getEncoded();` ended with `String keyString = new String(Base64.encode(enc_key));` then send the "keyString" into a database, load the key with `Base64.decode(keyString)`then formatted both the key, it works. Now i'm really going to my verification code. Thanks terminator. – Rhony Dec 29 '14 at 13:03
  • sorry, you got a little false again when verify the message :) we must run the update method with the original message because the ori_messg are in null condition before going to verify process, code something like this `byte[] ori_message = \\ ...` `dsa.update(ori_message);` then we can run the verify `dsa.verify(message_hash);` and now the boolean return true. Thanks for your usefull answer :) , please update your "verify" answer. – Rhony Dec 30 '14 at 14:15
  • @anIndonesian I kinda omitted it as it was basically the same as signing, but I added it just to make it clear. – initramfs Dec 30 '14 at 14:23