Thursday, August 14, 2008

 

SignatureTool (byte to char to byte)

之前要把簽章的值放到文字檔案內
簽章後得到的值是byte[]
放到文字檔案則需要String,或是char[]
但不知道為什麼
總是會出現 java.security.SignatureException: invalid encoding for signature
我試過許多byte轉成char的方式
包括自己位元運算硬寫出來的
用了不下四、五種API
看了一堆encoding的東西之後還是會有問題
實在是相當納悶
不過最後終於找到下面這種用BigInteger來轉的方式才OK


package swanky.util;

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 SignatureTool {
  public static byte[] getSignature(String message, PrivateKey privKey) {
    byte[] signature = null;
    try {
      // initial signature object
      Signature signalg = Signature.getInstance("DSA");
      signalg.initSign(privKey);

      // sign message
      signalg.update(message.getBytes());
      signature = signalg.sign();

    } catch (Exception e) {
      e.printStackTrace();
    }
    return signature;
  }

  public static boolean verify(String message, PublicKey pubKey,
      byte[] signature) {
    boolean result = true;
    try {
      // initial signature object
      Signature verifyalg = Signature.getInstance("DSA");
      verifyalg.initVerify(pubKey);

      // update signature object
      verifyalg.update(message.getBytes());

      if (!verifyalg.verify(signature))
        result = false;
    } catch (java.security.SignatureException se) {
      se.printStackTrace();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return result;
  }

  private static final int KEYSIZE = 512;

  public static void main(String[] args) throws Exception {
    String message = "test";

    KeyPairGenerator pairgen = KeyPairGenerator.getInstance("DSA");
    SecureRandom random = new SecureRandom();
    pairgen.initialize(KEYSIZE, random);
    KeyPair keyPair = pairgen.generateKeyPair();

    PublicKey pubKey = keyPair.getPublic();
    PrivateKey privKey = keyPair.getPrivate();

    byte[] signature = getSignature(message, privKey);
    System.out.println("raw signature: " + signature.toString());

    String encodeSig = toHexString(signature);
    System.out.println("string signature: " + encodeSig);

    byte[] decodeSig = fromHexString(encodeSig);
    System.out.println("signature: " + decodeSig);

    boolean result = verify(message, pubKey, decodeSig);
    System.out.println("verify result=" + result);

    result = verify(message + "fake", pubKey, decodeSig);
    System.out.println("verify result=" + result);
  }

  public static String toHexString(byte[] in) {
    BigInteger temp = new BigInteger(in);
    return temp.toString(16);
  }

  public static byte[] fromHexString(String in) {
    BigInteger temp = new BigInteger(in, 16);
    return temp.toByteArray();
  }
}

執行結果

raw signature: [B@1bf73fa
string signature: 302d0215008a1cf6cb2a0228fb8a4330f308c19789e1992bb5021444db35e4c9f40b5efce53e9ea3c3821b3d3d4058
signature: [B@5740bb
verify result=true
verify result=false

但是呢你看
原本簽章的值跟轉回來的簽章值print出來的東西不一樣耶...
這到底是怎麼回事? @@"

Labels: , , ,