如何亲自进行电子签名

我将立即进行预订-我几乎是与电子数字签名(EDS)有关的业余爱好者。最近,出于自然的好奇心,我决定进行一些整理,并在Internet上找到100500篇文章,主题是在各个认证中心获取数字签名证书,以及有关使用各种现成的应用程序对文档进行签名的大量说明。在某些地方,提到了如果您使用“经验丰富的程序员”的服务,则可以独立制作非熟练的签名。


我也想至少成为一些“经验丰富”的人,并从内部了解这个厨房。为了好玩,我学习了如何生成PGP密钥,使用不合格的签名对文档进行签名以及验证其真实性。尽管了解到没有美国是开放的,但我还是为与我在数字签名方面工作的业余爱好者提供了这个简短的教程。我并不是特别想深入研究理论和细节,而是只写一个简短而简短的问题简介。对于已经使用EDS的人来说,这不太可能有趣,但是对于初学者来说,这是第一次认识-恰到好处。


什么是电子签名


所有术语和定义均在法律中给出,因此,我们将以您自己的话语陈述所有内容,而不会假装该措辞的绝对法律准确性。


电子数字签名(EDS)是工具的集合,可以清楚地验证文档的作者(或动作的执行者)是否是自称作者的人。从这个意义上讲,EDS完全类似于传统签名:如果通常的“纸质”文件表明其作者是Ivanov,而Petrov的签名在下面,那么您可以怀疑Ivanov的作者身份。


电子签名既简单增强简单的签名并不意味着使用标准的密码算法;EDS时代之前发明的所有身份验证方法(授权)-本质上是简单的电子签名。例如,如果您在公共服务网站上注册,通过出现在多功能中心中来验证您的身份,然后通过该网站向各个政府机构发出上诉,则在这种情况下,来自公共服务网站的用户名和密码将是您的简单电子签名。


我曾经遇到过一种在一个组织中对电子文档进行身份验证的方法:在发送文档之前,准备好其哈希值 ( , ). ( ) , . , : , fetch- ajax- . , : , .


. ; , , . - ( , , ), : . ; (public key), — (private key). , , .


, ( ? ) , , , . , , , . , , , .


, : , — . ( ) . , , , , - ! . ( ), , .


. , . : . ( ) . , , , , .


. (detach), . , - .


? : , . :


  • ;
  • , ;
  • , , ( ). !

, , , «». , . , , . : , . , ...


. , , , ( , ). ( ), . , , (fingerprint), , , . , , , , , . , ( 40 ).


, , , — , . . : , ( ). , , .


, (, ) , . , ( ): .


, : - (, ) . , , .


, ( ) ( ). , (, ). (, ) , , .



, . , , , (public key) (private key).


. , , PGP (Pretty Good Privacy). 1991 , (, OpenPGP). 1999 GNU Privacy Guard (GnuPG, GPG). GPG ; - Windows , , gpg4win. - .


, (- , - root')


gpg --full-generate-key

:


  • «RSA RSA ( )»;
  • , 2048 ;
  • « »;
  • , , , ; ;
  • , .

GPG , . , , , GPG . , , , .


( , , , , ) :


gpg --export -a "  " > public.key
gpg --export-secret-key -a "  " > private.key

, private.key , public.key .



, (ASCII) :


gpg -ba __

, asc. , , privet.doc, privet.doc.asc. , , privet.sig, .


, , , :


#!/usr/bin/python
# -*- coding: utf-8 -*-
from Tkinter import *
from tkFileDialog import *
import os, sys, tkMessageBox

def die(event):
    sys.exit(0)

root = Tk()
w = root.winfo_screenwidth()//2 - 400
h = root.winfo_screenheight()//2 - 300
root.geometry("800x600+{}+{}".format(w, h))
root.title(" ")

flName = askopenfilename(title=" ?")

if flName:
    os.system("gpg -ba " + flName)
    button = Button(text=" ")
    button.bind("<Button-1>", die)
    button.pack(expand=YES, anchor=CENTER)
else:
    die()

root.mainloop()


, , , ( ) , :


gpg --verify __ __

- (, ):


  • public.key , () , , GPG;
  • - , .

- ( , ) .


, OpenPGP.js; ( — 506 ) dist/lightweight/openpgp.min.js html- ( meta-):


<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body>

<label for="doc">   </label>
<input id="doc" type="file" onChange="readDoc('doc')">

<label for="sig">   </label>
<input id="sig" type="file" onChange="readDoc('sig')">

<button type="button" disabled onClick="check()"></button>
<output></output>

<script src="openpgp.min.js"></script>
<script src="validate.js"></script>

</body>
</html>

, public.key openpgp.min.js , .


validate.js:


"use strict";
let cont   = {doc:'', sig:''},
    flag   = {doc:false, sig:false},
    pubkey = '',
    mess   = '';

//    ( ),
//    ( )
const readDoc = contKey => {
    let reader = new FileReader();
    reader.onload  = async e => {
        cont[contKey] = contKey == "sig" ?
                        e.target.result :
                        new Uint8Array(e.target.result);
        flag[contKey] = true;
        pubkey = await (await fetch("public.key")).text();   
        if (flag["doc"] && flag["sig"])
            document.querySelector("button").disabled = false;
    }
    reader.onerror = err => alert("  ");

    let fileObj = document.querySelector(`#${contKey}`).files[0];
    if (contKey == "sig") reader.readAsText(fileObj);
    else                  reader.readAsArrayBuffer(fileObj);
}

//  
const check = async () => {
    try {   
       const verified = await openpgp.verify({
           message:    openpgp.message.fromBinary(cont["doc"]),
           signature:  await openpgp.signature.readArmored(cont["sig"]),
           publicKeys: (await openpgp.key.readArmored(pubkey)).keys
       });
       const {valid} = verified.signatures[0];
       mess = "    !";
       if (valid) mess = "   .";
    } catch(e) {mess = "    .";}
    document.querySelector("output").innerHTML = mess;
}

实际上,仅此而已。现在,根据GOST 7.0.97–2016的第5.23条您可以将这张精美的图片放在文档上(应该是手写签名的位置):



All Articles