- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我需要使用 BouncyCaSTLe 加密提供程序通过 Java 验证 ECDSA 签名。到目前为止,BouncyCaSTLe 无法验证签名。
签名是在Atmel AT88CK590 Crypto Authentication模块中创建的,公钥可以从模块中获取。这是 C/C++ 格式的公钥,长度为 64 个八位字节:
uint8_t pubKey[] = {
// X coordinate of the elliptic curve.
0xc1, 0x71, 0xCB, 0xED, 0x65, 0x71, 0x82, 0x2E, 0x8F, 0x8A, 0x43, 0x8D, 0x72, 0x56, 0xD1, 0xC8,
0x86, 0x3C, 0xD0, 0xBC, 0x7F, 0xCC, 0xE3, 0x6D, 0xE7, 0xB7, 0x17, 0xED, 0x29, 0xC8, 0x38, 0xCB,
// Y coordinate of the elliptic curve.
0x80, 0xCD, 0xBE, 0x0F, 0x1D, 0x5C, 0xC5, 0x46, 0x99, 0x24, 0x8F, 0x6E, 0x0A, 0xEA, 0x1F, 0x7A,
0x43, 0xBA, 0x2B, 0x03, 0x80, 0x90, 0xE9, 0x25, 0xB2, 0xD0, 0xE6, 0x48, 0x93, 0x91, 0x64, 0x83
};
Base64编码的原始消息、签名和公钥:
// Raw message to sign
private static final String tokenStr = "12345678901234567890123456789012";
// Base64 encoded
private static final String pubKeyStr = "wXHL7WVxgi6PikONclbRyIY80Lx/zONt57cX7SnIOMuAzb4PHVzFRpkkj24K6h96
Q7orA4CQ6SWy0OZIk5Fkgw==";
// Base64 encoded
private static final String signatureStr = "XF2WossFTA82ndYFGEH0FPqAldkFQLGd/Bv/Qh8UYip7sXUvCUnFgi1YXjN3WxLn
IwSo3OaHLCOzGAtIis0b3A==";
要转换公钥,我使用以下内容:
private static PublicKey getPublicKeyFromBytes(byte[] pubKey, String ecSpec, String provider)
throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(ecSpec);
KeyFactory kf = KeyFactory.getInstance(ECDSA_CRYPTO, provider);
ECNamedCurveSpec params = new ECNamedCurveSpec(ecSpec, spec.getCurve(), spec.getG(), spec.getN());
ECPoint pubPoint = ECPointUtil.decodePoint(params.getCurve(), pubKey);
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(pubPoint, params);
PublicKey publicKey = kf.generatePublic(pubKeySpec);
return publicKey;
}
要将签名转换为 DER 格式,我使用以下内容:
private static byte[] toDERSignature(byte[] tokenSignature) throws IOException {
byte[] r = Arrays.copyOfRange(tokenSignature, 0, tokenSignature.length / 2);
byte[] s = Arrays.copyOfRange(tokenSignature, tokenSignature.length / 2, tokenSignature.length);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
DEROutputStream derOutputStream = new DEROutputStream(byteArrayOutputStream);
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new ASN1Integer(new BigInteger(1, r)));
v.add(new ASN1Integer(new BigInteger(1, s)));
derOutputStream.writeObject(new DERSequence(v));
byte[] derSignature = byteArrayOutputStream.toByteArray();
return derSignature;
}
验证签名的代码如下:
Security.addProvider(new BouncyCastleProvider());
byte[] tokenBytes = tokenStr.getBytes("UTF-8");
String urlDecodePubKeyStr = pubKeyStr.replace(newlineHtml, "");
byte[] pubKeyBytes = DatatypeConverter.parseBase64Binary(urlDecodePubKeyStr);
String urlDecodeSignatureStr = signatureStr.replace(newlineHtml, "");
byte[] signBytes = DatatypeConverter.parseBase64Binary(urlDecodeSignatureStr);
byte[] derSignature = toDERSignature(signBytes);
ByteBuffer bb = ByteBuffer.allocate(pubKeyBytes.length + 1);
bb.put((byte)4);
bb.put(pubKeyBytes);
PublicKey ecPublicKey = getPublicKeyFromBytes(bb.array(), "prime256v1", "BC");
System.out.println("\nSignature: " + Hex.toHexString(signBytes).toUpperCase());
System.out.println("DER Signature: " + Hex.toHexString(derSignature).toUpperCase());
System.out.println(ecPublicKey.toString());
Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
signature.initVerify(ecPublicKey);
signature.update(tokenBytes);
boolean result = signature.verify(derSignature);
System.out.println("BC Signature Valid: " + result);
输出:
Signature: 5C5D96A2CB054C0F369DD6051841F414FA8095D90540B19DFC1BFF421F14622A7BB1752F0949C5822D585E33775B12E72304A8DCE6872C23B3180B488ACD1BDC
DER Signature: 304402205C5D96A2CB054C0F369DD6051841F414FA8095D90540B19DFC1BFF421F14622A02207BB1752F0949C5822D585E33775B12E72304A8DCE6872C23B3180B488ACD1BDC
EC Public Key
X: c171cbed6571822e8f8a438d7256d1c8863cd0bc7fcce36de7b717ed29c838cb
Y: 80cdbe0f1d5cc54699248f6e0aea1f7a43ba2b038090e925b2d0e64893916483
BC Signature Valid: false
有没有人遇到过同样的问题?我在这里错过了什么?
最佳答案
该签名值不是像标准和通常那样在散列上计算,而是直接在数据上计算。要么:
Atmel 不进行哈希处理,因此您必须先进行哈希处理并提供要签名的哈希输出
Atmel 应该散列,但您没有设置一些必要的选项或其他内容
您实际上想要一个没有散列的非常规“原始”签名。请注意,这将数据限制为 32 或 31 个字节。如果要签名的值可能会受到对手的影响并且用于签名的随机生成器很弱,我认为这会导致恢复您的私钥的攻击(尽管我还没有完成)。即使有 if,我也会避免这种风险。
无论如何,您拥有的值可以使用方案 NoneWithECDSA
进行验证。
此外,在对此进行测试时,我发现您的代码中有一些您可能想要或可能不想要的改进。首先,你不需要准编码然后解码点,假设你有固定格式的 X,Y,你可以直接使用它们。其次,您确实需要对签名进行 DER 编码,但这可以更简单地完成。这是我的版本,为了清楚起见,在一个线性 block 中进行了两项更改:
public static void main (String[] args) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
// test data; real data would come from outside
byte[] dataBytes = "12345678901234567890123456789012".getBytes("UTF-8");
String sigString = "XF2WossFTA82ndYFGEH0FPqAldkFQLGd/Bv/Qh8UYip7sXUvCUnFgi1YXjN3WxLn
IwSo3OaHLCOzGAtIis0b3A==";
String pubkeyString = "wXHL7WVxgi6PikONclbRyIY80Lx/zONt57cX7SnIOMuAzb4PHVzFRpkkj24K6h96
Q7orA4CQ6SWy0OZIk5Fkgw==";
String ecSpec="prime256v1"; int size=32; // bytes for x,y in pubkey also r,s in sig
byte[] pubkeyBytes = DatatypeConverter.parseBase64Binary(pubkeyString.replaceAll("
","") );
KeyFactory kf = KeyFactory.getInstance ("ECDSA", "BC");
ECNamedCurveParameterSpec cspec = ECNamedCurveTable.getParameterSpec(ecSpec);
BigInteger x = new BigInteger(1, Arrays.copyOfRange(pubkeyBytes,0,size));
BigInteger y = new BigInteger(1, Arrays.copyOfRange(pubkeyBytes,size,size*2));
ECPublicKeySpec kspec = new ECPublicKeySpec (cspec.getCurve().createPoint(x, y), cspec);
PublicKey k = kf.generatePublic(kspec);
byte[] sigBytes = DatatypeConverter.parseBase64Binary(sigString.replaceAll("
","") );
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(/*r*/new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(sigBytes,0,size))));
v.add(/*s*/new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(sigBytes,size,size*2))));
byte[] sigDer = new DERSequence(v).getEncoded();
Signature sig = Signature.getInstance("NoneWithECDSA", "BC"); // NOTE None instead of a hash
sig.initVerify (k); sig.update (dataBytes);
System.out.println ("verify="+sig.verify(sigDer));
}
PS:您将公钥的一半注释为 椭圆曲线的 X [Y] 坐标
。它们是公钥曲线上点的坐标;曲线本身没有坐标。
关于java - 使用 prime256v1 和 SHA256withECDSA 算法的 BouncyCaSTLe ECDSA 签名验证失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39714906/
这个问题在这里已经有了答案: C - determine if a number is prime (12 个答案) 关闭 4 年前。 这是 C 程序。这是我的code在下面。我用了nano在终端。
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
和17一样,是质数,反过来,71也是质数。 我们设法得到了这段代码,但我们无法完成它。 #include main() { int i = 10, j, c, sum, b, x, d, e
好像is-prime和 .is-prime区别对待他们的论点: > is-prime('11') True > '11'.is-prime No such method 'is-prime' for
我正在尝试收集有关素数的一些统计数据,其中包括数字 (prime-1)/2 的因数分布。我知道有统一选择数的因子大小的通用公式,但我还没有看到任何关于小于一个素数的因子分布的信息。 我编写了一个程序,
BigInteger的JavaDoc让我感觉很不安全,例如下面的构造函数说: BigInteger(int bitLength, int certainty, Random rnd) Construc
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
我需要将蓝牙模块连接到A-Star 32U4 Prime SV microSD,但无法使其工作。作为背景,我有一个Pololu双G2大功率电机驱动器24v18盾牌Arduino连接到它。。该项目是一个
我需要将蓝牙模块连接到A-Star 32U4 Prime SV microSD,但无法使其工作。作为背景,我有一个Pololu双G2大功率电机驱动器24v18盾牌Arduino连接到它。。该项目是一个
一 构建后的图 二 实现 package graph.prim; import java.util.Scanner; public class Prim { static final in
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 9年前关闭。 Improve this q
我需要编写一个程序来输入一个数字并以以下形式输出其阶乘的质因数分解: 4!=(2^3)*(3^1) 5!=(2^3)*(3^1)*(5^1) 问题是我仍然不知道如何得到那个结果。 显然,括号中的每个第
我目前正在做一个项目,我需要一种有效的方法来计算素数。我使用了sieve of Eratosthenes,但是我一直在搜索,发现sieve of Atkin是一种更有效的方法。我发现很难找到对此方法的
我想找到总和为给定值的最小素数集,例如9 = 7 + 2(不是 3+3+3)。 我已经使用 sieve of eratosthens 生成了一个素数数组 我按降序遍历数组,以获得数组中小于或等于给定数
我正在学习 Real World Haskell(我在第 4 章),为了进行一些课外练习,我创建了以下程序来计算第 n 个素数。 import System.Environment isPrime p
我试图发现大数分解的复杂性。 哪一个是最佳算法,哪一个是找到数字的素因数的复杂性?假设数字的长度为n。 最佳答案 用于分解大于100个数字的整数的最知名算法是General number field
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Generating the partitions of a number Prime number sum
让我们看看我们想要找到 1 到 1000 之间的所有数字,这些数字表示为两个素数之和。例如 8 = 3+5, 24 = 13+11 现在这可以通过迭代 1 到 1000 之间的素数列表在 O(n^2)
我学会了一种叫做“线性筛”的算法https://cp-algorithms.com/algebra/prime-sieve-linear.html能够在线性时间内得到所有小于 N 的素数。 这个算法有
我正在学习 Idris,作为个人练习,我想实现一个 Primes类型,由所有素数组成。 在 idris 中是否有一种方法可以从一个类型和一个属性开始定义一个新类型,它将选择该属性为真的起始类型的所有元
我是一名优秀的程序员,十分优秀!