如何使用Ubuntu命令行工具和我自己的密钥对文件签名?


14

我想对我编写的一些Python代码文件进行签名,因为它们是我的一个项目的插件模块。为了分发它,我希望用户可以确保插件经过验证且安全(因为是由我或我信任的人编写的)并且未被修改。

该软件只是一个开源的业余项目,因此我不想花任何钱来购买正式证书。取而代之的是,我假设主程序始终是有效的,并且可以在不进行额外验证的情况下被信任。如果有人从我的GitHub存储库以外的任何其他位置下载它,那是他们的错。

据我所读,签名通常是通过创建一个非对称密钥对,从代码文件中计算一个强加密哈希值(例如SHA-512),使用我的私钥加密哈希并将该签名存储在单独的文件中来完成的。随原始代码文件一起提供。
然后,主程序将不得不使用保存在主程序源代码中的纯文本格式的公钥来解密签名,计算出与代码文件相同的哈希函数,然后将其与解密后的公钥进行比较。如果它们匹配,则可以信任该插件。

所以现在我的问题是:

如何使用Ubuntu工具轻松创建强大的非对称密钥对,以及如何轻松计算文件的加密哈希值?
在脚本中自动执行签名过程(始终使用相同的密钥)将非常有用。

Answers:


19

这个答案大部分都来自Arch WikiGnuPG文档。我对这个答案的任何建议纯属我的看法,应与一吨盐一起服用。

创建PGP密钥

图形用户界面

  1. 打开“ 密码和密钥”应用程序(aka seahorse),然后单击+(或转到File- > New,或按CtrlN)以查看:

    海马的新项目对话框

  2. 选择PGP密钥,然后输入您的详细信息。我正在扮演Byte Commander:

    键详细信息对话框

    RSA和2048位适用于大多数用途。如果您只想使用它进行签名,请从下拉菜单中选择RSA(仅签名)选项,但您不必这样做-可以使用子键来处理。您可以留言。在密钥上保留有效期也很有用。点击Create

  3. 输入适当的长密码(我的意思是long,我的示例是IMO),然后单击Ok

    密码输入对话框

    与CLI不同,Seahorse似乎没有任何反馈。等待一会儿,做任何您想做的事,同时它收集熵并创建一个密钥。它可能需要一段时间。之后,您将在“ PGP密钥”部分中看到它们的密钥:

    pgp键列表

命令行界面

要从命令行生成密钥,只需运行gpg --gen-key。它将要求您提供与GUI相同的详细信息:

$ gpg --gen-key 
gpg (GnuPG) 1.4.16; Copyright (C) 2013 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 
Requested keysize is 2048 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 1y
Key expires at Tuesday 27 September 2016 03:45:19 PM IST
Is this correct? (y/N) y

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and E-mail Address in this form:
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: Byte Commander
E-mail address: byte@command.er
Comment: 
You selected this USER-ID:
    "Byte Commander <byte@command.er>"

Change (N)ame, (C)omment, (E)-mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.

passphrase not correctly repeated; try again.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, use the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy!  (Need 186 more bytes)
.....+++++
+++++
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, use the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy!  (Need 80 more bytes)
....+++++

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy!  (Need 83 more bytes)
...+++++
gpg: key 8AE670A6 marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   2  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: next trustdb check due at 2016-09-26
pub   2048R/8AE670A6 2015-09-28 [expires: 2016-09-27]
      Key fingerprint = 82D9 0644 B265 8E75 1E01  538B B479 3CF4 8AE6 70A6
uid                  Byte Commander <byte@command.er>
sub   2048R/0E2F4FD8 2015-09-28 [expires: 2016-09-27]

注意GnuPG如何告诉我们它需要更多的熵。希望海马也这样做。但话又说回来,感觉像GnuPG的行为就像Oliver Twist。:P

发布密钥

现在,我们需要将公开密钥放在那里,以便人们可以使用它来验证事物。

图形用户界面

返回到seahorse应用程序中的PGP密钥列表(请参阅最后的屏幕截图)。选择要导出的密钥,然后在“ 远程”菜单中,选择“ 同步和发布密钥”

在此处输入图片说明

Sync如果您尚未选择要发布到的服务器,则该按钮将被禁用。通过单击Key Servers按钮来这样做:

在此处输入图片说明

我选择了Ubuntu的服务器。

现在,您可以单击Sync按钮并将其发布到Ubuntu的密钥服务器(对不起,垃圾邮件,Ubuntu!)。

命令行界面

使用CLI,您需要要发布的密钥的密钥ID。这是创建键(8AE670A6)时输出的最后一行。如果您不记得它是什么,请运行gpg --list-keys。发布:

$ gpg  --keyserver pgp.mit.edu --send-keys 8AE670A6
gpg: sending key 8AE670A6 to hkp server pgp.mit.edu

抱歉,麻省理工学院

签收

我还不知道签名文档的便捷GUI方法。

创建要签名的文件后,转到终端。尝试gpg --list-keys

$ gpg --list-keys       
/home/muru/.gnupg/pubring.gpg
---------------------------
pub   2048R/F7878B0C 2015-09-28 [expires: 2016-09-26]
uid                  Byte Commander <byte@command.er>
sub   2048R/345B9A4F 2015-09-28 [expires: 2016-09-26]

您可以使用两种方法对文件签名:

加密签名

$ gpg --sign --output examples.sig examples.desktop 

You need a passphrase to unlock the secret key for
user: "Byte Commander <byte@command.er>"
2048-bit RSA key, ID F7878B0C, created 2015-09-28

gpg: Invalid passphrase; please try again ...

You need a passphrase to unlock the secret key for
user: "Byte Commander <byte@command.er>"
2048-bit RSA key, ID F7878B0C, created 2015-09-28

如果您正在进行桌面会话,则可能会收到图形密码提示。例如,在GNOME中:

在此处输入图片说明

如果收件人拥有您的公钥,他们可以对其进行验证或获取解密的内容:

$ gpg --verify examples.sig
gpg: Signature made Monday 28 September 2015 03:25:00 PM IST using RSA key ID F7878B0C
gpg: Good signature from "Byte Commander <byte@command.er>"
$ gpg --decrypt examples.sig
[Desktop Entry]
Version=1.0
Type=Link
Name=Examples
Name[aa]=Ceelallo
...
URL=file:///usr/share/example-content/
Icon=folder
X-Ubuntu-Gettext-Domain=example-content

gpg: Signature made Monday 28 September 2015 03:25:00 PM IST using RSA key ID F7878B0C
gpg: Good signature from "Byte Commander <byte@command.er>"

用明文签名

例如,在发送邮件时,您可能不想加密内容。在这种情况下,请使用以下--clearsign选项:

$ gpg --clearsign examples.desktop 

You need a passphrase to unlock the secret key for
user: "Byte Commander <byte@command.er>"
2048-bit RSA key, ID F7878B0C, created 2015-09-28

$ cat examples.desktop.asc 
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

[Desktop Entry]
Version=1.0
Type=Link
Name=Examples
Name[aa]=Ceelallo
...
URL=file:///usr/share/example-content/
Icon=folder
X-Ubuntu-Gettext-Domain=example-content

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQEcBAEBAgAGBQJWCRAaAAoJEGUZkqX3h4sMBWsH/1yw+G0v5Ck+T3PBS90SkvC8
5C0FJeGVr0AgYQohhsE3zEGQ7nn53N7JsvNlF6VccvN99DZIp18JbrJ+qs5hWjtg
KU/ACleR5dvVrJgfjppkuC8Q3cAudvqciKlLjA7Xycr3P49oCNCy8k/ue2TrgCvS
mMb5IS/kqpO7wrOMBAR0c/2CjQsA91S1/YK7DbuUqeNgEzW1grsI7XZPhiDGpAib
D20HWrbdLhklAEJuo1EvuOIggW6MF6ksxDoVapsUzQalD0TWEq6OnvzIS5qhITrc
XaDPQJpiHyCyINnL5aZCUwr2uon7osJ+2a8Ahp1REpzIZTdND9jA5NWSel5+yAs=
=ZrtB
-----END PGP SIGNATURE-----

签名,使用单独的文件进行签名(分离的签名)

最后,对于某些文件,您不能在文档中具有签名。例如,打包文件或存储库的元数据都具有特定性质的内容,这些内容不容易允许嵌入签名。在这种情况下,请使用以下--detached-sig选项:

$ gpg --output examples.desktop.sig --detach-sign examples.desktop

You need a passphrase to unlock the secret key for
user: "Byte Commander <byte@command.er>"
2048-bit RSA key, ID F7878B0C, created 2015-09-28

$ gpg --verify examples.desktop.sig examples.desktop
gpg: Signature made Monday 28 September 2015 03:35:55 PM IST using RSA key ID F7878B0C
gpg: Good signature from "Byte Commander <byte@command.er>"

注意

在加密+签名和分离签名中,的输出gpg为二进制。您可以使用--armor选项(ASCII装甲)使GnuPG输出base64编码的数据。

自动化

要进行脚本签名,您可以:

  • 使用空密码作为密钥
  • 根据您的GnuPG版本,通过发送密码短语stdin。有关某些选项,请参见此Unix&Linux帖子

非常好的和详细的答案。但是关于您创建的示例密钥...我不知道我是否对假名周围有一组未使用的密钥感到满意。如果以后我想用该名称创建实键并使用它们,则搜索它们的人可能会感到困惑。我猜您的示例密钥和我的真实密钥将由于不同的电子邮件地址而能够共存,因此获得不同的ID,但是……您是否有可能再次删除这些密钥?
字节指挥官

@ByteCommander该术语被撤销。我会考虑撤销它们。为此,我应该添加一个有关撤销密钥的部分。
muru

@ByteCommander对不起,我删除了我发布的密钥(并且没有做出吊销证书(经典的n00b错误),因此我无法撤销该密钥。但是,它的有效期为一年,所以,任何混乱都将在一年内解决
大师

好吧-发生了。不知道是让我烦恼还是应该为那个愚蠢的错误而笑...我认为对于我的项目,我宁愿使用Python模块rsa,该模块可以轻松地对数据进行签名而不会遇到所有GPG问题。一旦我开始实际发布和打包软件,这可能会变得非常有用,但就目前而言,对于我的目的而言可能太过庞大了。所以在那之前它可能会过期!:)
字节指挥官

我想都是@ByteCommander。尽管我建议您在创建密钥时使用真实姓名,并在评论字段中留下昵称。
muru

4
  1. 用gpg创建一个非对称密钥

    gpg --gen-key
    
  2. 使用gpg对文件进行签名(已使用您的私钥)

    gpg --output foo.sig --detach-sig foo.py
    
  3. 测试签名文件(使用您的公共密钥)

    gpg --verify foo.sig foo.py
    

    输出示例

    % gpg --verify foo.sig foo.py 
    gpg: Signature made Mo 28 Sep 2015 12:46:04 CEST using RSA key ID 89B30DEC
    gpg: Good signature from "Your Name <your.name@host.com>"
    
    % echo "bad" >> foo.py
    
    % gpg --verify foo.sig foo.py
    gpg: Signature made Mo 28 Sep 2015 12:46:04 CEST using RSA key ID 89B30DEC
    gpg: BAD signature from "Your Name <your.name@host.com>"
    
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.