数字签名及验证功能实现思路

本文分享了将数字签名功能集成到实际项目中的实现思路。在表单提交时进行签名,查看时进行校验,以防数据被后台篡改。设计思路包括在提交时组装签名数据,保存原文和密文,查看时进行签名验证,确保数据完整性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这几天研究了下数字签名相关的功能,简单分享下实现的思路。因签名及验证已封装成插件,故本文不对具体的签名功能及验签功能进行讲解,只分享如何集成到实际项目中。

需求

在表单提交的时候进行签名,查看时可以对该单据数据进行签名校验。

目的

防止数据被后台私自篡改,有理有据。

设计思路
  1. 表单编辑页面,点击提交时,自行组装需要进行签名验证的数据,拼接成json字符串原文;
  2. 调用签名插件进行签名,并获取签名后的密文信息;
  3. 调用后台方法,保存原文、密文、以及当前表单的唯一标识ID;
  4. 表单查看页面,点击验签,获取当前页面对应的需要进行签名验证的数据,拼接成json字符串原文(格式保证和步骤1拼接的原文一致);
  5. 根据表单唯一标识ID查询对应数据库存储的密文;
  6. 最后调用签名插件的验证方法进行数据验证(传参为步骤4获取的原文+步骤5查询的密文),验证成功则说明数据未被篡改。
表设计
-- Create table
create table SIGN_INFOMATION
(
  id          VARCHAR2(32) not null,
  business_id VARCHAR2(32),
  user_name   VARCHAR2(50),
  user_id     VARCHAR2(
### Java 实现 SM2 数字签名算法的设计思路 #### 1. 算法背景介绍 SM2 是我国自主研发的椭圆曲线公钥密码算法,主要用于实现数字签名和密钥交换等功能。该算法基于椭圆曲线上离散对数问题(ECDLP),提供了较高的安全性。 #### 2. 密钥生成 在实现过程中,首先需要生成一对匹配的公私钥: - **私钥**:随机选取一个小于n的大整数d作为私钥; - **公钥**:计算Q=dG (其中G为基点,n为其阶), Q即为对应的公钥; ```java // 私钥 d 的生成 BigInteger d = new BigInteger(n.bitLength(), random).mod(n.subtract(BigInteger.TWO)).add(BigInteger.ONE); // 计算公钥 Q = d * G ECPoint Q = ecParams.getG().multiply(d); ``` [^1] #### 3. 签名过程 对于给定的消息m, 使用私钥d对其进行签名: - 对消息 m 进行哈希得到 z=Hash(m) ; - 随机选择 k ∈ [1,n−1]; - 计算 R=k×G=(x₁,y₁); - 如果R是无穷远点,则重新选择k; - 将 x₁ 转换成大端序编码形式 e=x₁ mod n; - s ≡ (z+de)/k(mod n); 若s=0则重选k; - 输出(r,s)=(e,s). ```java byte[] msgBytes = message.getBytes(); byte[] hashValue = sm3Digest.digest(msgBytes); BigInteger e = new BigInteger(1, hashValue); BigInteger r; do { BigInteger k = generateK(ecParams.getOrder()); ECPoint point = ecParams.getG().multiply(k); byte[] encodedX = point.normalize().getAffineXCoord().toByteArray(); r = new BigInteger(1, Arrays.copyOfRange(encodedX, encodedX.length - fieldSize / 8, encodedX.length)); } while (r.equals(ZERO)); BigInteger s = k.modInverse(ecParams.getOrder()).multiply(e.add(privateKey.multiply(r))).mod(ecParams.getOrder()); return new Signature(r, s); ``` [^4] #### 4. 验证过程 接收方收到消息及其签名字样后,按照如下方式验证: - 获取发送者的公钥P; - 检查r,s 是否属于区间[1,n-1], 否则返回失败; - u₁=z/s;u₂=r/s; - V=u₁*G + u₂*P =(x₀,y₀); - v=x₀ mod n; - 判断v是否等于r. ```java boolean verify(byte[] message, Signature signature){ if (!signature.r.signum() > 0 && !signature.s.signum() > 0 || signature.r.compareTo(order) >= 0 || signature.s.compareTo(order) >= 0 ) return false ; byte[] msgBytes = message.getBytes(); byte[] hashValue = sm3Digest.digest(msgBytes); BigInteger e = new BigInteger(1,hashValue ); BigInteger c = signature.s.modInverse(order ); BigInteger u1 = e.multiply(c ).mod(order ); BigInteger u2 = signature.r.multiply(c ).mod(order ); ECPoint pukey = publicKey.multiply(u2); ECPoint basepoint = curve.getG (). multiply(u1); ECPoint sum = pukey.add(basepoint ); byte[] encodedX = sum.normalize (). getAffineXCoord (). toByteArray (); BigInteger v = new BigInteger(1 ,Arrays .copyOfRange (encodedX ,encodedX .length -(fieldSize /8 ),encodedX .length )); return v.equals(signature.r); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值