1. 前言

类似在纸质合同上签名确认合同内容,数字签名用于证实某数字内容的完整性( integrity)和来源( 或不可抵赖,non-repudiation)。
一个典型的场景是,A 要发给 B 一个文件( 一份信息) ,B 如何获知所得到的文件即为 A 发出的原始版本?A 先对文件进行摘要,然后用自己的私钥进行加密,将文件和加密串都发给B。B 收到文件和加密串后,用 A 的公钥来解密加密串,得到原始的数字摘要,跟对文件进行摘要后的结果进行比对。如果一致,说明该文件确实是 A 发过来的,并且文件内容没有被修改过。

2. DSA

签名s应当是秘密数字x,消息的哈希值H(m)和随机数字k的一个函数。s=f(x,H(m),k)

我们如何在不知道x和k的情况下验证该等式呢。

我们可以借助于上章学习的离散对数问题。y=g^x mod p 和r=g^k mod p发送给接受者,不用担心x和k的泄露。一般称x为私钥,y为公钥,<r,s>为数字签名。

签名关系F和签名函数f是等价的,而验签关系G是由F决定的。因此关系F是决定签名方案的关键。

我们最容易想到的一种方案是让 中各数字之间有加法运算,如:

s=x+k+H(m)mod(p-1)

所以,G应当为:g^s≡g^(x+k+H(m)) mod p=g^xg^kg^H(m) mod p≡yr g^H(m) mod p

所以,接收方需要验证关系:g^s≡yr * g^H(m) mod p是否成立就可以验证签名了。

但是目前仍然存在问题,即正常的签名是可以通过验证的啊,但是可能被攻击者进行攻击。攻击者很容易在不知晓x和k的情况下,伪造签名r和s。

那么如何进行伪造呢?

攻击者只要先对s任取一值s’,然后通过解方程g^s≡yr * g^H(m) mod p,得到r'≡g^s'/(y * g^H(m)) mod p。

显然满足上述公式的r'和s'也可以验证通过。

所以我们必须修改方案,可以借助上面学习的离散对数问题,可以让验签方案中的s和都出现在指数上,这样攻击者就必须解决离散对数问题,才可能实施攻击。所以我们需要调整验签方案G和签名方案F。

我们可以将签名关系F修改为:sk≡H(m)+xr (mod (p-1)),则签名函数s为s=(H(m)+xr) /k mod(p-1),即k=(H(m)+xr) /s mod(p-1),所以有:r=g^k mod p=g^(H(m)+xr)/s mod p=g^(H(m))/s * g^(r/s) mod p

在该等式的结果中,仅包含签名<r,s>,公钥y和消息m,不会泄露私钥x,k。所以可以使用该等式作为验签关系:

G:r=g^(H(m))/s * g^(r/s) mod p由于r和s都在指数上,所以攻击者无法伪造签名。

总计一下,我们的DSA的签名方案为:

r=g^k mod p;

s=(H(m)+xr) /k mod(p-1)

验签方案为:

r=g^(H(m))/s * g^(r/s) mod p

事实上,上面的方案还是存在着不足,即为了防止离散对数数学问题不被暴力破解,通常素数p的值需要很大,为了减小数字签名的规模,我们需要采取一定的措施:

选择一个相对较小的整数q,使q满足g^q mod p=1,如果 p取1024比特,那么q就取160比特。

这样,s和q修改为相同的规模,r的大小不变。所以我们需要把r缩减为同等规模。即r修改为

r= (g^(H(m)/s * y^(r/s) mod p)) mod q;

到此,我们总结下,DSA的签名方案为:

签名过程:

第一步,生成参数素数p,素数q,底数 g,满足g^q mod p=1;用户公钥为:随机选取x,计算公钥y = g^x mod p.

第二步,对每一个消息m,生成随机数 k,1<k<q;

第三步,计算r=(g^k mod p) mod p,若r=0,重复该步骤;

第四步,计算s=(H(m)+xr)/k mod q,若 s=0,重复该步骤;

第五步,令<r,s>为数字签名。

第二步和第三步是为每条消息产生一个密钥,

验证过程:

检查该过程是否成立:

  • 0<r<q;
  • 0<s<q;
  • w=s^-1 mod q
  • u1=H(m)*w mod q
  • u2=r*w mod q
  • v = (g^u1* y^u2 mod p) mod q
  • 判断v和r是否相等。

算法的正确性验证:

总结:

第一,为了防止泄露私钥 ,只能公开公钥 ;

第二,为了防止伪造签名,必须在验签方案中让签名出现在指数上;

第三,为了减小数字签名规模,为指数选择一个相对较小的模数。

而这一切都建立在素数域GF(p)中的整数加法、乘法、幂和离散对数的运算性质上。

如果将素数域更换为有限域上的椭圆曲线,运算的对象变为椭圆曲线上的点,那么仍然可以定义出具有类似性质的加法、乘法。参照我们的DSA探秘之路,你自己就可以设计出具有更高安全性的椭圆曲线数字签名方案ECDSA,而ECDSA正是比特币体系使用的数字签名方案。

3. ECDSA

Parameter
CURVE the elliptic curve field and equation used
G elliptic curve base point, such as a pt {\displaystyle (x_{0},y_{0})} on {\displaystyle y^{2}=x^{3}+7}, a generator of the elliptic curve with large prime order n
n integer order of G, means that {\displaystyle n\times G=O}, where {\displaystyle O} is the identity element.

椭圆曲线签名算法原理,椭圆曲线签名算法,即ECDSA。
设私钥、公钥分别为k、K,即K = kG,其中G为G点。

签名过程如下:

  1. 选择一条椭圆曲线Ep(a,b),和基点G;

2、选择私有密钥k(k<n,n为G的阶),利用基点G计算公开密钥K=kG;

3、产生一个随机整数r(r<n),计算点R=rG;

4、将原数据和点R的坐标值x,y作为参数,计算SHA1做为hash,即Hash=SHA1(原数据,x,y);

5、计算s≡r - Hash * k (mod n)

6、r和s做为签名值,如果r和s其中一个为0,重新从第3步开始执行

验证过程如下:

1、接受方在收到消息(m)和签名值(r,s)后,进行以下运算

2、计算:sG+H(m)P=(x1,y1), r1≡ x1 mod p。

3、验证等式:r1 ≡ r mod p。

4、如果等式成立,接受签名,否则签名无效。

原理如下
hG/s + xK/s = hG/s + x(kG)/s = (h+xk)G/s = r(h+xk)G / (h+kx) = rG

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;/*** 椭圆曲线签名算法* * 速度快 强度高 签名短* * 实现方 JDK1.7/BC*/public class ECDSAUtil {private static String str = "hello";public static void main(String[] args) {jdkECDSA();}public static void jdkECDSA() {try {//第一步:初始化化秘钥组,生成ECDSA算法的公钥和私钥KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");keyPairGenerator.initialize(256);KeyPair keyPair = keyPairGenerator.generateKeyPair();ECPublicKey ecPublicKey = (ECPublicKey) keyPair.getPublic();ECPrivateKey ecPrivateKey = (ECPrivateKey) keyPair.getPrivate();System.out.println("PublicKey:"+ecPublicKey.toString());// 2.执行签名PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());KeyFactory keyFactory = KeyFactory.getInstance("EC");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);Signature signature = Signature.getInstance("SHA1withECDSA");signature.initSign(privateKey);signature.update(str.getBytes());byte[] sign = signature.sign();System.out.println("signResult:"+sign.toString());//3.验证签名X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(ecPublicKey.getEncoded());keyFactory = KeyFactory.getInstance("EC");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);signature = Signature.getInstance("SHA1withECDSA");signature.initVerify(publicKey);signature.update(str.getBytes());boolean bool = signature.verify(sign);System.out.println(bool);} catch (Exception e) {e.printStackTrace();}}
}

4. HMAC

全称是 Hash-based Message Authentication Code,即“基于 Hash 的消息认证码”。基本过程为对某个消息,利用提前共享的对称密钥和 Hash 算法进行加密处理,得到 HMAC 值。该HMAC 值提供方可以证明自己拥有共享的对称密钥,并且消息自身可以利用 HMAC 确保未经篡改。
HMAC(K, H, Message)
其中,K 为提前共享的对称密钥,H 为提前商定的 Hash 算法( 一般为公认的经典算法) ,Message 为要处理的消息内容。如果不知道 K 和 H,则无法根据 Message 得到准确的HMAC 值。

HMAC 一般用于证明身份的场景,如 A、B 提前共享密钥,A 发送随机串给 B,B 对称加密处
理后把 HMAC 值发给 A,A 收到了自己再重新算一遍,只要相同说明对方确实是 B。

HMAC 主要问题是需要共享密钥。当密钥可能被多方拥有的场景下,无法证明消息确实来自某人( Non-repudiation) 。反之,如果采用非对称加密方式,则可以证明。

5. 盲签名

1983 年由 David Chaum 提出。签名者在无法看到原始内容的前提下对信息进行签名。

盲签名主要是为了实现防止追踪( unlinkability) ,签名者无法将签名内容和结果进行对应。典型的实现包括 RSA 盲签名)。

6. 多重签名

n 个持有人中,收集到至少 m 个 的签名,即认为合法,这种签名被称为多重签名。其中,n 是提供的公钥个数,m 是需要匹配公钥的最少的签名个数。

7. 群签名

1991 年由 Chaum 和 van Heyst 提出。群签名属于群体密码学的一个课题。

群签名有如下几个特点:只有群中成员能够代表群体签名( 群特性) ;接收者可以用公钥验证群签名( 验证简单性) ;接收者不能知道由群体中哪个成员所签( 无条件匿名保护) ;发生争议时,群体中的成员或可信赖机构可以识别签名者( 可追查性) 。

Desmedt 和 Frankel 在 1991 年提出了基于门限的群签名实现方案。在签名时,一个具有 n个成员的群体共用同一个公钥,签名时必须有 t 个成员参与才能产生一个合法的签名,t 称为门限或阈值。这样一个签名称为(n, t)不可抵赖群签名。

8. 环签名

环签名由 Rivest,shamir 和 Tauman 三位密码学家在 2001 年首次提出。环签名属于一种简化的群签名。

签名者首先选定一个临时的签名者集合,集合中包括签名者自身。然后签名者利用自己的私钥和签名集合中其他人的公钥就可以独立的产生签名,而无需他人的帮助。签名者集合中的其他成员可能并不知道自己被包含在其中。

转载于:https://www.cnblogs.com/anapodoton/p/10686750.html

区块链中的密码学之数字签名方案(十二)相关推荐

  1. 区块链中的密码学(五)-零知识证明简述

    本篇是这个系列的最后一篇,尽管在区块链中还有很多的密码学应用,将来会必然会更多,然而笔者认为,就今天我们有限的学习时间来讲的话,任何人都应该对信息的获取做减法.思来想去,选择了"零知识证明& ...

  2. 区块链中的密码学应用

    区块链中应用到的密码学主要包括以下几方面: 数字摘要 区块链本质上是一种分布式数据存储方式,每一个数据区块之间靠数字摘要建立起联系,比如比特币中每一个区块都包含了它前一个区块的摘要值.因此数字摘要是区 ...

  3. 区块链中的密码学系列之SHA256算法(三)

    1. 前言 SHA系列算法是一种密码散列函数,由美国国家安全局设计,并由美国国家标准技术研究所(NIST)发布为联邦数据处理标准(FIPS).现在已经被破解. 我们本文主要研究SHA256算法. 2. ...

  4. 解密区块链中的密码学

    在这片文章中,我们总结了区块链会用到的一些密码学原语,那什么是密码学"原语"? 不同于操作系统的"原语"概念,(注:操作系统原语是操作系统或计算机网络用语范畴. ...

  5. 区块链中的密码学,使用ABE结合区块链

    ABE 密码学,以及与区块链结合的价值 背景 区块链技术具备篡改难度高.使用成本低.分布式的优点,本应成为各行各业的重要助力.但是由于链上参与方担心自己的核心数据外泄,不愿将自己的核心数据上链,这个原 ...

  6. 【问链财经-区块链基础知识系列】 第三十二课 从区块链溯源来看农产品链的设计

    在区块链的应用场景中,农产品溯源和食品溯源一直是翻来覆去讲的故事,但实际上溯源是一个伪命题,农产品和食品的加密上链实现溯源看起来很丰满,然而现实却很骨干.我们经常忘记了初心:溯源的目的是为了什么? 农 ...

  7. 区块链中密码学与安全技术

    区块链的定义 区块链的定义,应当是:区块链是一种按照时间顺序将数据进行分布式存储的块链式数据结构,它利用共识机制进行数据验证,利用密码学进行数据保护和用户安全访问,利用智能合约来操作数据,从而成为不可 ...

  8. 密码学简史(二)--- 区块链中的现代密码学

    文章目录 5. 对称钥匙:DES加密法 6. 非对称钥匙:RSA加密法 6.1 不可逆模运算 --- DH密钥交换 6.2 RSA加密法 6.3 数字签名 6.4 比特币中的密码学 6.5 区块链中的 ...

  9. 区块连中的密码学--SHA256实现机制

    区块连中的密码学–SHA256实现机制 摘要 本文主要介绍区块链中所使用的密码学知识,同时因为Hash函数是区块链中重要的一环,因此也使用python3对SHA256进行了实现. 一.什么是区块链 关 ...

最新文章

  1. 【转载】django在eclipse环境下建web网站
  2. ABAP:SAP报表性能的优化
  3. Redis 安装启动
  4. Event Bus 设计模式学习笔记
  5. SpringCloud系列七:使用Ribbon实现客户端侧负载均衡
  6. JAVA面试常考系列十一
  7. SpringCache与Redis
  8. Java 中的细节补充
  9. dmg镜像 os vm 安装mac_dmg制作笔记:个性化自己的Mac软件安装包
  10. @transactional可以用在controller层吗_石晶地板可以用在浴室吗?
  11. 什么是序列化?序列化的作用是什么?iOS中怎么实现序列化?
  12. 七月算法--12月机器学习在线班-第九次课笔记—推荐系统
  13. Mysql-slowlog
  14. 使用网云穿「内网穿透」实现外网访问内网瑞友天翼等软件
  15. uploadify上传
  16. Ubuntu中报错:failed to create hard link
  17. 模拟爬虫下载QQ空间相册高清图片
  18. 201912月全国计算机二级考试,201912月天津计算机二级报名时间:12月5日-12月7日!附报名入口...
  19. AlphaGo人肉臂黄士杰:我的使命完成 阿尔法狗项目结束 | 重磅
  20. 云数据库产品及架构设计背后的考量

热门文章

  1. 【总结】2014新生暑假个人排位赛02
  2. vue解构赋值_vue解构赋值_ES6解构赋值
  3. 计算机那个网络连接不见了,电脑开机进入系统的时候发现网络连接图标不见了怎么办...
  4. 【ADRC】跟踪微分器
  5. pgsql 根据时间戳取unixtime
  6. 程序员的数学之寻找恋人
  7. UML02 - 静态视图
  8. 全球各大邮件SMTP服务限制
  9. Docker容器化实战第八课 DevOps和CI/CD
  10. python mkl使用_直接从python调用intel的mkl时,请使用多个线程