好的,我想在 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;
}
}
谢谢!