Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/180.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当我只有原始签名(R,S)和原始公钥点(Qx,Qy)时,如何用Java验证ECDSA数据块_Java_Android_Cryptography_Ecdsa - Fatal编程技术网

当我只有原始签名(R,S)和原始公钥点(Qx,Qy)时,如何用Java验证ECDSA数据块

当我只有原始签名(R,S)和原始公钥点(Qx,Qy)时,如何用Java验证ECDSA数据块,java,android,cryptography,ecdsa,Java,Android,Cryptography,Ecdsa,我得到了一个字节数组消息以及签名的四个32字节原始组件:Qx、Qy、R和S。如何将它们格式化/编码为ECPublicKey和byte[]函数期望的签名?签名是用SHA-256 ECDSA创建的。解决方案需要结合其他两个答案(并用Java实现): 创建公钥需要生成一个伪密钥对,并使用其ECParameterSpec,然后替换原始公钥点[Qx,Qy]。还必须从原始字节创建biginger。这可以在下面的createPublicKey函数中看到 签名(由R和S组成)必须以DER格式进行编码-我

我得到了一个字节数组消息以及签名的四个32字节原始组件:QxQyRS。如何将它们格式化/编码为
ECPublicKey
byte[]
函数期望的签名?签名是用SHA-256 ECDSA创建的。

解决方案需要结合其他两个答案(并用Java实现):

创建公钥需要生成一个伪密钥对,并使用其
ECParameterSpec
,然后替换原始公钥点[Qx,Qy]。还必须从原始字节创建
biginger
。这可以在下面的
createPublicKey
函数中看到

签名(由R和S组成)必须以DER格式进行编码-我找不到现有的Java实用程序函数来执行此操作,因此它是手动完成的,如下面的
CreateDersignature
所示

/**
*检查“message”是否与签名[R,S]和公钥点[qx,qy]匹配
*
*@param消息设备ID
*@param r ECDSA签名的第一部分
*@param的ECDSA签名的第二部分
*@param qx是公钥点的一部分
*@param qy是公钥点的一部分
*@return true如果签名在消息上签名
*@note ECDSA SHA-256已使用-r、s、qx和qy的长度必须为32字节
*/
私有静态布尔值ecdsaVerify(@NotNull final byte[]消息,@NotNull final byte[]r,@NotNull final byte[]s,
@NotNull最终字节[]qx,@NotNull最终字节[]qy)
{
尝试
{
//将原始字节转换为“签名”可以理解的内容
ECPublicKey publicKey=createPublicKey(qx,qy);
字节[]derSignature=createdersignature(r,s);
//进行实际验证
Signature sig=Signature.getInstance(“SHA256withECDSA”);
sig.initVerify(公钥);
信号更新(信息);
返回信号验证(签名);
}
捕获(NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException | SignatureException | InvalidAlgorithmParameterException e)
{
返回false;
}
}
/**
*使用NIST P-256格式化原始椭圆曲线点[qx,qy]
*
*@param qx x x坐标-应为32字节
*@param qy y坐标-应为32字节
*@从原始坐标返回公钥
*@见https://stackoverflow.com/a/22652372/1229250
*/
专用静态ECPublicKey createPublicKey(字节[]qx,字节[]qy)
抛出NoSuchAlgorithmException、InvalidAlgorithmParameterException、InvalidKeySpecException
{
//生成伪造的密钥对,以便获得其规格
KeyPairGenerator kpg=KeyPairGenerator.getInstance(“EC”);
kpg.initialize(新的ECGenParameterSpec(“secp256r1”);//NIST P-256
ECPublicKey apub=(ECPublicKey)kpg.generateKeyPair().getPublic();
ECParameterSpec aspec=apub.getParams();
ECPoint点=新的ECPoint(新的BigInteger(1,qx),新的BigInteger(1,qy));
ECPublicKeySpec pks=新的ECPublicKeySpec(点,aspec);
return(ECPublicKey)KeyFactory.getInstance(“EC”).generatePublic(pks);
}
/**
*以DER格式对原始签名进行编码
*
*@param r原始签名的第一部分-应为32字节
*@param原始签名的第二部分-应为32字节
*@返回DER格式的签名
*@见https://crypto.stackexchange.com/a/57734/89173
*/
专用静态字节[]createdSignature(字节[]r,字节[]s)
{
//向后建造
字节[]der={};
der=终点(der,s);
der=终点(der,r);
返回前置标题(der);
}
/**
*获取原始坐标值'p',然后将其换行并在'derSig'前面加上前缀`
*
*包装包括按(0x02)添加标题、长度以及前导零(如果需要)。
*
*@param derSig到目前为止DER格式签名的结尾(可能为空)
*@param p要预加的坐标的一部分
*@返回到目前为止带有添加组件的签名
*/
私有静态字节[]prependPoint(字节[]derSig,字节[]p)
{
//如果前导*位*为1,则追加一个零字节(因此作为一个整体,它是一个正数)
最终布尔值prependZero=(p[0]&0x80)=0x80;
最终int pointLength=p.length+(prependZero?1:0);
最终int prependSize=2+点长度;
最终整型totalNewSize=prependSize+derSig.length;
字节[]结果=新字节[totalNewSize];
结果[0]=2;
结果[1]=(字节)点长度;
if(prependZero)
{
结果[2]=0;
}
系统数组副本(p,0,结果,prependZero?3:2,p.length);
System.arraycopy(derSig,0,result,prependSize,derSig.length);
返回结果;
}
/**
*添加DER标题-0x30幻数和点的长度
*
*@param derSig到目前为止的DER签名-必须有两点
*@返回带有正确标题的签名
*/
专用静态字节[]prependHeader(字节[]derSig)
{
字节[]结果=新字节[derSig.length+2];
结果[0]=0x30;
结果[1]=(字节)derSig.length;
数组复制(derSig,0,result,2,derSig.length);
返回结果;
}