信息安全主要关注信息的三个重要属性,完整性、保密性、可用性。
数字签名主要用于确保数据的完整性。
博主想确保博客的完整性,通过数字签名可以验证博文是否被他人转载后修改了。
比如有的博文带有“未经许可禁止转载”声明的博文。如果某站未经许可爬了我的博客,同时修改声明为“允许转载”,因为博客园发布的博客可以再编辑,但不支持博客的版本管理,所以我很难证明我从未给出“允许转载”的声明。针对这种情况,数字签名可以给出有效的证据,这是如何做到的呢?首先,博主会对每篇博客做数字签名。如果文章转载后被篡改,数字签名验证会失败。
当然,数字签名也可以保护转载文章的人。说不定哪天博主不小心把博文许可从“允许转载”改为“未经许可禁止转载”。因为已经被转载的博文带有有效的数字签名,也可以证明博主以前的确给出过“允许转载”的声明,博主自己想耍赖也不行。
从2019年7月20日开始,采用的签名算法为 SHA384 + ECDSA384。
数字签名验证过程的几个重点:
1)正确的公钥也是确保有效数字签名的关键。博主所有博文的数字签名必须使用下面的公钥验证。
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEsrblD3gHjQKPJHWO0mpzaXhAmN95lrcB
VS2dC48mPhVBqFoH4MCEudMNJCnRG6FV9zWBeZIlE9wOtksYBNRgZgV/hH0/jzqe
Ts4Eq6HSS0tzorLTgPnQPNOmd+qPIs3M
-----END PUBLIC KEY-----
2)博主所有博文只对文本内容进行了数字签名,未对其他多媒体内容进行签名。
3)验签工具推荐使用基于 javascript
和 html
的 博客文本签名和验签工具 (见本文下方)。这个工具也支持生成签名哦。
4)同样的博客,不同浏览器复制得到的文本可能会不一样,从而导致验签失败。 博主博客的数字签名都是在火狐浏览上生成和测试过的。
博客文本签名和验签工具
下面的工具是博主生成签名和验证签名的工具,基于 javascript
和 html
。
验证签名的步骤 (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