Byronsh博客的数字签名的验证方法

信息安全主要关注信息的三个重要属性,完整性、保密性、可用性。

数字签名主要用于确保数据的完整性。

博主想确保博客的完整性,通过数字签名可以验证博文是否被他人转载后修改了。

比如有的博文带有“未经许可禁止转载”声明的博文。如果某站未经许可爬了我的博客,同时修改声明为“允许转载”,因为博客园发布的博客可以再编辑,但不支持博客的版本管理,所以我很难证明我从未给出“允许转载”的声明。针对这种情况,数字签名可以给出有效的证据,这是如何做到的呢?首先,博主会对每篇博客做数字签名。如果文章转载后被篡改,数字签名验证会失败。

当然,数字签名也可以保护转载文章的人。说不定哪天博主不小心把博文许可从“允许转载”改为“未经许可禁止转载”。因为已经被转载的博文带有有效的数字签名,也可以证明博主以前的确给出过“允许转载”的声明,博主自己想耍赖也不行。

从2019年7月20日开始,采用的签名算法为 SHA384 + ECDSA384。

数字签名验证过程的几个重点:

1)正确的公钥也是确保有效数字签名的关键。博主所有博文的数字签名必须使用下面的公钥验证。

-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEsrblD3gHjQKPJHWO0mpzaXhAmN95lrcB
VS2dC48mPhVBqFoH4MCEudMNJCnRG6FV9zWBeZIlE9wOtksYBNRgZgV/hH0/jzqe
Ts4Eq6HSS0tzorLTgPnQPNOmd+qPIs3M
-----END PUBLIC KEY-----

2)博主所有博文只对文本内容进行了数字签名,未对其他多媒体内容进行签名。

3)验签工具推荐使用基于 javascripthtml博客文本签名和验签工具 (见本文下方)。这个工具也支持生成签名哦。

4)同样的博客,不同浏览器复制得到的文本可能会不一样,从而导致验签失败。 博主博客的数字签名都是在火狐浏览上生成和测试过的。

博客文本签名和验签工具

下面的工具是博主生成签名和验证签名的工具,基于 javascripthtml

验证签名的步骤 (windows中):

1) 新建一个文本文件A(以.txt为后缀的文件)

2) 将下面的代码拷贝到文件A中

3) 将文件A的后缀从 .txt改为.html

4) 鼠标双击文件A,用浏览器打开,界面如下(红色文本为添加的注释)。

5) 博文结尾处带有签名,签名上方会有一条水平分割线。将水平分割线上方的博客正文拷贝到“文本”下面的编辑栏中。(注意:不要拷贝标题和博客结尾处的签名)

6) 将博文结尾处的签名拷贝到“签名”下的编辑框中

7) 博主博客验签的公钥已经默认在“公钥”下的编辑框中,保持不变;

8)对于验证数字签名,“私钥”不起作用,“私钥“下的编辑框保持不变;

9)点击最下方的按钮“验证签名”,然后会弹出验证结果。

<!DOCTYPE HTML>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <title>数字签名生成/验证</title>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/8.0.12/jsrsasign-all-min.js"></script>
<script>

/* 
 * function generateSignature()
 * 功能: 生成数字签名
 */
function generateSignature(){
  //1. 获取需要签名的文本
  var plain_text = document.getElementById("input").value;
  //为了减小网页排版导致的签名验证失败,删除所有的空字符(空格,换行符,制表符等等)
  plain_text_trim = plain_text.replace(/s*/g, "");

  //2. 用私钥签名
  //2.1 获取公钥 
  var prk = document.getElementById("prk").value;
  var sign_key = KEYUTIL.getKey(prk);
  //2.2 创建签名对象
  let signature = new KJUR.crypto.Signature({alg:"SHA384withECDSA"});

  //2.3 初始化签名对象的钥匙和需要签名的文本
  signature.init(sign_key);
  signature.updateString(plain_text_trim);
  //2.4 进行签名
  let a = signature.sign();
  let sign = hextob64(a);
  //2.5 将签名更新进网页的文本框
  document.getElementById("signature").value = sign + "
--- " + getDateTime();
  
  //3. 提醒用户签名完成
  document.getElementById("result").innerText = getDateTime() + " 签名成功。
" ;
};

/* 
 * function verifySignature()
 * 功能: 验证数字签名
 */
function verifySignature(){
  //1. 获取需要验证数字签名的文本及其签名
  //1.1 获取文本
  var plain_text = document.getElementById("input").value;
  //为了减小网页排版导致的签名验证失败,删除所有的空字符(空格,换行符,制表符等等)
  var plain_text_trim = plain_text.replace(/s*/g, "");
  //1.2 获取签名
  var signature = document.getElementById("signature").value;
  signature = signature.replace(/
---s*.*/,""); // remove "--- 2019-09-04"

  //2. 用公钥验证签名
  //2.1 获取公钥
  var puk = document.getElementById("puk").value;
  var verify_key = KEYUTIL.getKey(puk);
  //2.2 创建签名对象
  let signatureVf = new KJUR.crypto.Signature({alg:"SHA384withECDSA"}); 
  //2.3 初始化签名对象的钥匙和需要签名的文本
  signatureVf.init(verify_key);
  signatureVf.updateString(plain_text_trim);
  //2.4 验证签名
  let b = signatureVf.verify(b64tohex(signature));

  //3. 告知用户验签结果
  if(true == b){
    alert("签名 有效。");
    document.getElementById("result").innerHTML = "<p>" + getDateTime() + "  签名<b style='color:green'>有效</b></p>";
  }
  else{
    alert("签名 无效!!");
    document.getElementById("result").innerHTML = "<p>" + getDateTime() + "  签名<b style='color:red'>无效</b></p>";
  }
};

function getDateTime()
{
  var now = new Date();
  var year = now.getFullYear();
  var month = now.getMonth()+1;
  var date = now.getDate();
  var day = now.getDay();
  var hour = now.getHours();
  var minute = now.getMinutes();
  var second = now.getSeconds();

  var  dateTime = year+"-"+month+"-"+date+" "+hour+":"+minute+":"+second;
  return dateTime;
};

</script>
  </head>    

  <body>
    <div>
      <label for="input">文本:</label><br>
      <textarea id="input" name="input"  class=""></textarea><br>

      <label for="prk">私钥:</label><br>
      <textarea id="prk" name="prk"  class=""></textarea><br>

      <label for="puk">公钥:</label><br>
      <!--下面是用于验证byronsh博客文章数字签名默认公钥-->
      <textarea id="puk" name="puk"  class="">
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEsrblD3gHjQKPJHWO0mpzaXhAmN95lrcB
VS2dC48mPhVBqFoH4MCEudMNJCnRG6FV9zWBeZIlE9wOtksYBNRgZgV/hH0/jzqe
Ts4Eq6HSS0tzorLTgPnQPNOmd+qPIs3M
-----END PUBLIC KEY-----
      </textarea><br>

      <label for="signature">签名:</label><br>
      <textarea id="signature" name="signature"  class=""></textarea><br>
    </div>

    <div>
      <button id="btnGenSig" onclick="generateSignature()">生成签名</button>
      <button id="btnVeriSig" onclick="verifySignature()">验证签名</button><br>
    </div>
    <div id="result">
      <p>请点击按钮“验证签名”或“生产签名”</p>
    </div>
  </body>
</html>

历史

SHA512 + RSA4096

在2019年7月20日前,采用SHA512 + RSA4096 签名,其公钥如下。因为签名太长,所以启用了。

-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnrJo0wOPcH+ZeAb+UsGh
yHhPRiV4sox4aUf2SDHZVfCGUcpZJZQ5pi3QK0lNX4WuaBZ1HquhtU5s7uKqaJlf
mb1gGCJOG17bHACJV143XR+T7VQe9UmBBp8gpBbEsdYg9+4TJCti8vmDvfz0meJF
q9De5n9Uk2J2Gt2UQX+dpru8FnDmlI8AIt3eAyfJnY6XB4y9GymuXbyj6R238a6T
3udc7gK+50CgxVylBO5ANJ9YYDLkGv++9mAODlKXuE/xtG7XNXrTQ0f+NrlrRmDQ
qCFmAYK8GdT0eKkkT4gHBah7wYEVpw9iOcHzVpajp7vsMe33qO3IpMTFpJ+TkZd9
H/7gQ6Hu5QPzv236Ym4nLAVtLOxx2iCN2cXT7cmkGas/9oDrYx1TdAW0VSk9PA2H
KRKZOdy9XYNAN9HOTZcy8YfpLv5CN5OnA+Qpca3XHD3Xf2kYafV0hdMuhBY7EP4y
yAxQt6Ug+9qWE4jJg5lh6jSbuMdfqO2a2JjZCh5Z4PrX+Cdnh6r1rV7lvSFZmyWY
gsAuzGh2zip9FY/3Pdy+Y0Xb4PbvNWcc+R8LxF0PrFwwbiYRyC+tGPvUCQIyTHYd
PMwNqcuxVh2X/WqcK6YVHUmlo6wDsJIMONDPzFTnM4VdhB1KgA5I0awzf6UuGBug
X44OVTtMBuksYdiydc9wVokCAwEAAQ==
-----END PUBLIC KEY-----

版权声明:本文为博主原创,允许转载但必须注明原文地址。博客原文:https://www.cnblogs.com/byronsh/p/blog-signature-verification.html


本文的数字签名如下:

MGQCMAmQeUELrlFqW+eWW6M1pcIbvmCDQY2BRjWtBfy7fp6dF6fNppHKK4nV7N30TBCorQIwCngoLMtzdI2/1ZvrgNUFYxollXSYHynDk/uc3PwoV9FT7XeebKqxtdYKgfGfM4So
--- 2019-7-20 9:27:13

数字签名验证方法

原文地址:https://www.cnblogs.com/byronsh/p/blog-signature-verification.html