OK、Python で ecdsa を使用して署名し、Java で検証したいと思います。これを行うために、m2crypto を使用した短い Python スクリプトと、Bouncycastle を使用した短い Java アプリケーションを開発しました。
Pythonでキーを生成し、PythonでサインインしてPythonで検証すると機能し、Javaでキーを生成し、JavaでサインインしてJavaで検証すると機能しますが、キーを共有しようとすると、すべてが少し梨になります-成形。- Java から Python へ、またはその逆方向に共有できませんでした。
以下は、実行するとJavaの最後に到達し、「チェックに失敗しました」で「失敗」するという点で機能するはずですが、コードにエラーが見つかりません。おそらく本当に単純な/明白なバグだと確信しています:
1) 鍵の生成(python、m2crypt):
from M2Crypto import EC
key = EC.gen_params(EC.NID_secp112r2) # Picked a random NID...
key.gen_key()
key.save_key("ecpriv.pem", None)
key.save_pub_key("ecpub.pem")
2) 署名(python、m2crypt):
def bigint(string):
return int(string.encode('hex'), 16)
myhash = "hello" # Yes, this should be a sha1 of something but shouldn't matter?
key = EC.load_key('ecpriv.pem')
sigr, sigs = key.sign_dsa(myhash)
intr = bigint(sigr)
ints = bigint(sigs)
print (intr, ints)
「bigint」の使用は、m2crypt から返されたバイナリ文字列から、弾む城が必要とする大きな整数に変換することです。それをコピーしてアプリケーションに貼り付けます。
3) 検証(java、bouncycastle):
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.util.io.pem.PemReader;
import org.bouncycastle.util.io.pem.PemObject;
import java.math.BigInteger;
import java.io.FileReader;
class ECVerify {
public static void main(String[] args) {
System.out.println("EC Verification"); // Display the string.
String strmessage = "";
String sigr = "";
String sigs = "";
try {
strmessage = args[0];
sigr = args[1];
sigs = args[2];
} catch (Exception e) {
System.out.println("Bad Argument?");
System.out.println(e.toString());
System.out.println("java ECVerify message r s");
return;
}
try {
PemReader reader = new PemReader(new FileReader("ecpub.pem"));
PemObject poKey = (PemObject) reader.readPemObject();
byte[] poContent = poKey.getContent();
// Now we have a signature we have to try and verify
ECDSASigner mySignValidator = new ECDSASigner();
ECPublicKeyParameters myPublicKey = (ECPublicKeyParameters) PublicKeyFactory.createKey(poContent);
// From here down its all ok *I think*
mySignValidator.init(false, myPublicKey);
byte[] message = strmessage.getBytes();
System.out.println("Message: " + byteArrToHexStr(message));
System.out.println("Message: " + new BigInteger(sigr).toString() +" " + new BigInteger(sigs).toString());
boolean check = mySignValidator.verifySignature(message, new BigInteger(sigr), new BigInteger(sigs));
if(check) {
System.out.println("Check passed");
} else {
System.out.println("Check failed");
}
} catch (Exception e) {
System.out.println("Error in main:");
System.out.println(e.toString());
}
}
// What follows are just convenience functions for printing
public static String byteAsHexString ( byte b )
{
String rV = "";
int k = (int) b;
k = k & 0xff;
if ( k <= 0xf )
{
rV = rV + "0";
}
rV = rV + Integer.toHexString ( k );
return rV;
}
public static String byteArrToHexStr ( byte[] bs )
{
StringBuffer sb = new StringBuffer();
for(int i=0; i< bs.length; i++)
{
sb.append( byteAsHexString ( bs[i] ));
}
return sb.toString();
}
public static byte[] hexStrToByte(String hex) {
// look for sepeartor
StringBuffer tempBuf = new StringBuffer(hex);
for (int i=0; i<tempBuf.length(); i++) {
char c = tempBuf.charAt(i);
if (!((c >= 'A' && c <= 'F')|| (c >= 'a' && c <= 'f')|| (c >= '0' && c <= '9'))) {
tempBuf.deleteCharAt(i);
i--;
}
}
hex = tempBuf.toString();
byte[] bts = new byte[hex.length() / 2];
for (int i = 0; i < bts.length; i++) {
bts[i] = (byte) Integer.parseInt(hex.substring(2*i, 2*i+2), 16);
}
return bts;
}
}
ありがとう!