- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用标准(内置)DSA 类开发 Java (JDK 1.8) 应用程序以验证数字签名。
我有数据文件和预期的签名存储在文本文件中,如下所示:
// Signature part R:
4226 3F05 F103 E3BE 59BF 3903 37F8 0375 8802 5D8F.
// Signature part S:
AF21 15B0 16E4 1761 75B8 C7D4 F877 5AB7 26BB AE72.
请注意,签名以 (R,S) 对的形式表示,如 FIPS 186-3 NIST 标准所述。
为了验证签名,我从 java.security.Signature 调用方法 verify(byte[] signature)。此方法需要一个表示要验证的签名的字节数组。但是,我不知道如何将 (R,S) 对转换为字节数组。因此我无法验证签名。
所以,我想知道:
1) 有没有办法按照 verify() 方法将 (R, S) 对转换为 DSA 字节数组签名?或者,
2) 有没有办法从 Java Signature 实例类中获取 R 和 S 值,以便我可以将这些值与我拥有的值进行比较?
提前致谢。
编辑:@dave_thompson_085 提出的解决方案效果很好!完整源码见下:
// read DSA parameters from file or other means
BigInteger r = new BigInteger(...);
BigInteger s = new BigInteger(...);
BigInteger p = new BigInteger(...);
BigInteger q = new BigInteger(...);
BigInteger g = new BigInteger(...);
BigInteger y = new BigInteger(...);
// get the public key
KeySpec publicKeySpec = new DSAPublicKeySpec(y, p, q, g);
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
// read the input file to be checked and update signature
Signature signature = Signature.getInstance("SHA1withDSA");
signature.initVerify(publicKey);
File inputFile = new File(...);
try (BufferedInputStream is = new BufferedInputStream(new FileInputStream(inputFile))) {
byte[] buffer = new byte[1024];
while (is.available() != 0) {
int len = is.read(buffer);
signature.update(buffer, 0, len);
}
}
// convert (r, s) to ASN.1 DER encoding
// assuming you have r and s as !!positive!! BigIntegers
// (if you have unsigned byte[] as shown in your Q,
// use BigInteger r = new BigInteger (1, bytes) etc.
byte[] rb = r.toByteArray();
byte[] sb = s.toByteArray(); // sign-padded if necessary
// these lines are more verbose than necessary to show the structure
// compiler will fold or you can do so yourself
int off = (2 + 2) + rb.length;
int tot = off + (2 - 2) + sb.length;
byte[] der = new byte[tot + 2];
der[0] = 0x30;
der[1] = (byte) (tot & 0xff);
der[2 + 0] = 0x02;
der[2 + 1] = (byte) (rb.length & 0xff);
System.arraycopy(rb, 0, der, 2 + 2, rb.length);
der[off + 0] = 0x02;
der[off + 1] = (byte) (sb.length & 0xff);
System.arraycopy(sb, 0, der, off + 2, sb.length);
// verifies if the signature is valid
boolean isValid = signature.verify(des);
最佳答案
1A。普通 Java 加密(以及 DSA 和 ECDSA 的大多数但不是所有其他用途)所期望的形式是 ASN.1 DER 编码。 https://crypto.stackexchange.com/a/1797/12642解释了困难是什么,但没有完全告诉您如何去做。
1B。如果您有或可以安装 the BouncyCastle cryptoprovider jar,它包含一整套 ASN.1 例程。或者更容易它也包含具有 init
和 verifySignature(byte[], BigInteger, BigInteger)
的低级原语 org.bouncycaSTLe.crypto.signers.DSASigner
可访问。 (但是这个原语不做散列,所以先自己做。)
1C。如果您必须自己使用标准加密来完成:
// assuming you have r and s as !!positive!! BigIntegers
// (if you have unsigned byte[] as shown in your Q,
// use BigInteger r = new BigInteger (1, bytes) etc.
byte[] rb = r.toByteArray(), sb = s.toByteArray(); // sign-padded if necessary
// these lines are more verbose than necessary to show the structure
// compiler will fold or you can do so yourself
int off = (2+2)+rb.length, tot = off+(2-2)+sb.length;
byte[] der = new byte[tot+2];
der[0] = 0x30; der[1] = tot;
der[2+0] = 0x02; der[2+1] = rb.length; System.arraycopy(rb,0, der,2+2, rb.length);
der[off+0] = 0x02; der[off+1] = sb.length; System.arraycopy(sb,0, der,off+2, sb.length);
2. 您无法通过比较 r 和 s 来验证标准 DSA 签名。正如您通过阅读 FIPS186-3 第 4.5 和 4.6 节应该知道的那样,签名是随机的;为同一条消息计算两个(或更多)签名每次都会给出不同的 (r,s) 对——除非你重复足够多的次数来命中相同的 k,对于较早的 1024/160 组/平均尝试 2^159 次 key ,更多用于更新/更大的 key 。如果您有一百万台计算机,每台计算机每秒可以尝试一百万次,这仍然需要大约 16,000,000,000,000,000,000,000,000,000 年。
关于java - 如何在 Java 中验证给定 (R,S) 对的 DSA 签名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40589825/
在下面的代码中,我得到一个 uninitialized value警告,但仅限于第二个 given/when例子。为什么是这样? #!/usr/bin/env perl use warnings; u
整个“开关”功能是否已成为实验性的?在没有 Perl 的 future 版本破坏我的代码的情况下,我可以依赖其中的某些部分吗?一般来说,将稳定功能更改为实验性的政策是什么? 背景use feature
有没有办法在一个条件语句中写出如下语句? a和b不能同时等于5。 (a可以是5,b可以是5,但是a AND b不能是5) 最佳答案 正如克里斯指出的那样,您要查找的是逻辑异或,相当于逻辑不等于 !=:
我正在寻找一种算法来找到给定 n 条线段的所有交点。以下是来自 http://jeffe.cs.illinois.edu/teaching/373/notes/x06-sweepline.pdf 的伪
数组中有 N 个元素。我可以选择第一项最多 N 次,第二项最多选择 N-1 次,依此类推。 我有 K 个 token 要使用并且需要使用它们以便我可以拥有最大数量的项目。 arr = [3, 4, 8
我正在尝试修复法语文本中的语法性别,想知道是否有办法从某个词条中获取所有单词的列表,以及是否可以在此类列表中进行查找? 最佳答案 尝试: import spacy lemma_lookup = spa
我正在为 Win32 编写一个简单的自动化测试应用程序。它作为一个单独的进程运行,并通过 Windows API 访问目标应用程序。我可以阅读窗口层次结构,查找标签和文本框,并通过发送/发布消息等来单
在 nodeJs 中使用 Sequelize 时,我从 Sequelize 收到此错误,如下所示: { [SequelizeUniqueConstraintError: Validation erro
本文https://arxiv.org/pdf/1703.10757.pdf使用回归激活映射 (RAM) - 而不是类激活映射 (CAM) 来解决问题。有几篇文章描述了如何实现 CAM。但是我找不到
我正在研究 Mach 动态链接器 dyld。这个问题适用于所有 Apple 平台,但很高兴得到特定于平台的答案;我正在使用 ObjC,但如果对你有用的话,我也很乐意翻译 Swift。 The rele
我有一个包含数千个 Instagram 用户 ID 的列表。我如何获得他们的 Instagram 用户名/句柄? 最佳答案 你必须使用这个 Instagram API: https://api.ins
我在下面的代码: def main(args: Array[String]) { val sparkConf = new SparkConf().setAppName("Spark-Hbase").s
我有一个表格,其中包含从 1 到 10 的数字。(从 D2 到 M2) 假设A1中有03/09/2019 并且在B1中有06/09/2019 并且在C1中有Hello 在A 列中,我有多个系列的单词,
我想在给定服务对应的 URI 的情况下检索服务的注释(特别是 @RolesAllowed )。这是一个例子: 服务: @GET @Path("/example") @RolesAllowed({ "B
我看到 OraclePreparedStatementexecuteQuery() 表现出序列化。也就是说,我想使用相同的连接对 Oracle 数据库同时运行两个查询。然而,OraclePrepare
import java.util.Scanner; public class GeometricSumFromK { public static int geometricSum(int k,
我创建了一个抽象基类Page,它说明了如何构建动态网页。我正在尝试想出一种基于作为 HttpServletRequest 传入的 GET 请求生成 Page 的好方法。例如... public cla
我的字符串是一条短信,采用以下两种格式之一: 潜在客户短信: 您已收到 1 条线索 标题:我的领导 潜在客户 ID:12345-2365 警报设置 ID:890 短信回复: 您已收到 1 条回复 标题
我在 python 中有以下代码: class CreateMap: def changeme(listOne, lisrTwo, listThree, listFour, listfive):
这是在 Hibernate 上运行的 JPA2。 我想检索相同实体类型的多个实例,给定它们的 ID。其中许多已经在持久性上下文和/或二级缓存中。 我尝试了几种方法,但似乎都有其缺点: 当我使用 ent
我是一名优秀的程序员,十分优秀!