是否可以使用原始数据的SHA256哈希值来验证SHA256withRSA签名?

如何解决是否可以使用原始数据的SHA256哈希值来验证SHA256withRSA签名?

很长时间以来,我一直在使用X509证书处理签名。

ENTRYPOINT

并验证...

Dockerfile

非常简单。

但是最近我听说可以仅使用文档的SHA256哈希而不是整个文档来验证签名...

FROM node:latest
LABEL author="Karim"
RUN npm install -g @angular/cli
WORKDIR /var/www/angular-app
ENTRYPOINT ["ng","serve","--host","0.0.0.0"]

有可能吗?用Java会怎么样?

我从另一家公司听说,所以我无法访问源代码... =(

解决方法

简短的回答是

长答案必须与将签名与算法标识符包装在一起的编码有关,并且要归档“仅在哈希上验证”功能,您必须进行两次更改。

首先-将算法标识符添加到签名之前: 正如@President James K. Polk所写的那样,您必须添加一些额外的字节才能对验证功能的输入进行正确的编码。根据需要 在“ EMSA-PKCS1-v1_5”填充(此处描述:val())中,您必须添加一些字节来表示 用于计算哈希的算法。

我有点懒,并且将必需的字节作为硬编码字节数组放在前面,因此该版本仅在SHA-256 算法上有效-如果 您曾经使用过其他哈希算法,则需要更改前置字节:

String prependSha256String = "3031300D060960864801650304020105000420";
byte[] prependSha256 = hexStringToByteArray(prependSha256String);
int combinedLength = prependSha256.length + documentHash.length;
byte[] documentHashFull = new byte[combinedLength];
System.arraycopy(prependSha256,documentHashFull,prependSha256.length);
System.arraycopy(documentHash,prependSha256.length,documentHash.length);

第二个-使用其他RSA签名方案: 在完成SHA-256部分后,我们需要一个称为“ NonewithRSA”的“裸” RSA方案,因此您需要更改实例化,例如:

Signature signatureVerifyHash = Signature.getInstance("NonewithRSA");

这是两次RSA签名验证(旧的和“新的”一次)的结果:

verify the signature with the full document
sigVerified: true

verify the signature with the SHA256 of the document only
sigVerifiedHash: true

这是完整的工作代码:

import java.security.*;

public class MainSo2 {
    public static void main(String[] args) throws NoSuchAlgorithmException,InvalidKeyException,SignatureException {
        System.out.println("Is it possible to verify a SHA256withRSA signature with a SHA256 hash of the original data?");

        // create a rsa keypair of 2048 bit keylength
        KeyPairGenerator rsaGenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom random = new SecureRandom();
        rsaGenerator.initialize(2048,random);
        KeyPair rsaKeyPair = rsaGenerator.generateKeyPair();
        PublicKey publicKey = rsaKeyPair.getPublic();
        PrivateKey privateKey = rsaKeyPair.getPrivate();

        String document = "The quick brown fox jumps over the lazy dog";
        // sign
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(document.getBytes());
        byte[] sig = signature.sign();

        // verify with full message
        System.out.println("\nverify the signature with the full document");
        Signature signatureVerify = Signature.getInstance("SHA256withRSA");
        signatureVerify.initVerify(publicKey);
        signatureVerify.update(document.getBytes());
        boolean sigVerified =  signatureVerify.verify(sig);
        System.out.println("sigVerified: " + sigVerified);

        // verify just the sha256 hash of the document
        System.out.println("\nverify the signature with the SHA256 of the document only");
        byte[] documentHash = MessageDigest.getInstance("SHA-256").digest(document.getBytes());
        // you need to prepend some bytes: 30 31 30 0D 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20
        // see https://tools.ietf.org/html/rfc3447#page-41
        // warning: this string is only for SHA-256 algorithm !!
        String prependSha256String = "3031300D060960864801650304020105000420";
        byte[] prependSha256 = hexStringToByteArray(prependSha256String);
        int combinedLength = prependSha256.length + documentHash.length;
        byte[] documentHashFull = new byte[combinedLength];
        System.arraycopy(prependSha256,prependSha256.length);
        System.arraycopy(documentHash,documentHash.length);
        // lets verify
        Signature signatureVerifyHash = Signature.getInstance("NonewithRSA");
        signatureVerifyHash.initVerify(publicKey);
        // signatureVerifyHash.update(document.getBytes());
        signatureVerifyHash.update(documentHashFull);
        boolean sigVerifiedHash =  signatureVerifyHash.verify(sig);
        System.out.println("sigVerifiedHash: " + sigVerifiedHash);
    }

    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i),16) << 4)
                    + Character.digit(s.charAt(i + 1),16));
        }
        return data;
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-