此软件包包含了一个简单的 GPG 包装器实现

1.0.1 2017-01-07 10:51 UTC

This package is not auto-updated.

Last update: 2024-09-23 14:23:40 UTC


README

简介

此软件包实现了围绕 PGP 命令行工具的包装。

请注意,此包装器的目标不是“完整”。这个包装器是为了自动化处理大量文件的 GPG 流程而开发的。因此,仅包装了基本的 GPG 功能(签名、加密、解密和签名验证)。

许可证

此代码按照以下许可证发布

知识共享署名-非商业性 4.0 国际(CC BY-NC 4.0)

请参阅文件 LICENSE.TXT

安装

从命令行

composer require dbeurive/gpg

或者,从文件 composer.json 中安装

"require": {
    "dbeurive/gpg": "*"
}

概述

// Get the fingerprint of a key.

$fgp = Gpg::getPublicKeyFingerPrint('protected key');
$fgp = Gpg::getPrivateKeyFingerPrint('protected key');

// Remove a key from the keyring.

Gpg::removePublicKey($fgp);
Gpg::removePrivateKey($fgp);

// Import a key into the keyring.

Gpg::importPublicKey('open.pub');
Gpg::importPrivateKey('open.prv');

// Check that a key is in the keyring.

Gpg::isPublicKeyPresent($fgp);
Gpg::isPrivateKeyPresent($fgp);

// Sign (encrypt with a private key).

Gpg::signFile('/path/to/document', $fgp, 'my password (if any), or null', '/path/to/encrypted_file');
Gpg::signFile('/path/to/document', $fgp, null, '/path/to/encrypted_file');
Gpg::signString('AZERTY', $fgp, 'my password (if any), or null', '/path/to/encrypted_file');
Gpg::signString('AZERTY', $fgp, null, '/path/to/encrypted_file');

$encryptedString = Gpg::signFile('/path/to/document', $fgp, 'my password (if any), or null', null);
$encryptedString = Gpg::signFile('/path/to/document', $fgp, null, null);
$encryptedString = Gpg::signString('AZERTY', $fgp, 'my password (if any), or null', null);
$encryptedString = Gpg::signString('AZERTY', $fgp, null, null);

// Clear sign

Gpg::clearSignFile('/path/to/document', $fgp, 'my password (if any), or null', '/path/to/signed_document');
Gpg::clearSignFile('/path/to/document', $fgp, null, '/path/to/signed_document');
Gpg::clearSignString('AZERTY', $fgp, 'my password (if any), or null', '/path/to/signed_document');
Gpg::clearSignString('AZERTY', $fgp, null, '/path/to/signed_document');

$signedDocument = Gpg::clearSignFile('/path/to/document', $fgp, 'my password (if any), or null', null);
$signedDocument = Gpg::clearSignFile('/path/to/document', $fgp, null, null);
$signedDocument = Gpg::clearSignString('AZERTY', $fgp, 'my password (if any), or null', null);
$signedDocument = Gpg::clearSignString('AZERTY', $fgp, null, null);

// Detach sign

Gpg::detachSignFile('/path/to/document', $fgp, 'my password (if any), or null', '/path/to/signature');
Gpg::detachSignFile('/path/to/document', $fgp, null, '/path/to/signature');
Gpg::detachSignString('AZERTY', $fgp, 'my password (if any), or null', '/path/to/signature');
Gpg::detachSignString('AZERTY', $fgp, null, '/path/to/signature');

$signature = Gpg::detachSignFile('/path/to/document', $fgp, 'my password (if any), or null', null);
$signature = Gpg::detachSignFile('/path/to/document', $fgp, null, null);
$signature = Gpg::detachSignString('AZERTY', $fgp, 'my password (if any), or null', null);
$signature = Gpg::detachSignString('AZERTY', $fgp, null, null);

// Verify a "clear" signature (that is: a file that contains the document and it signature)

$warning = null;
$status = Gpg::verifyClearSignedFile('/path/to/signed_document', $warning); // true: valid signature, false: invalid signature.
$status = Gpg::verifyClearSignedString($signature, $warning); // true: valid signature, false: invalid signature.

// Verify a "detached" signature (against a document)

$warning = null;
$status = Gpg::verifyDetachedSignedFile('/path/to/signature', '/path/to/document', $warning);
$status = Gpg::verifyDetachedSignedString($signature, '/path/to/document', $warning);

// Encrypt with a public key

Gpg::encryptAsymmetricFile('/path/to/document', $fgp, '/path/to/encrypted_file');
Gpg::encryptAsymmetricString('AZERTY', $fgp, '/path/to/encrypted_file');

$encryptedString = Gpg::encryptAsymmetricFile('AZERTY', $fgp, null);
$encryptedString = Gpg::encryptAsymmetricString('AZERTY', $fgp, null);

// Decrypt a document

Gpg::decryptFile('/path/to/encrypted_file', 'my password (if any), or null', '/path/to/decrypted_file');
Gpg::decryptFile('/path/to/encrypted_file', null, '/path/to/decrypted_file');
Gpg::decryptString($encryptedString, 'my password (if any), or null', '/path/to/decrypted_file');
Gpg::decryptString($encryptedString, null, '/path/to/decrypted_file');

$decryptedString = Gpg::decryptFile('/path/to/encrypted_file', 'my password (if any), or null', null);
$decryptedString = Gpg::decryptFile('/path/to/encrypted_file', null, null);
$decryptedString = Gpg::decryptString($encryptedString, 'my password (if any), or null', null);
$decryptedString = Gpg::decryptString($encryptedString, null, null);

有关返回码的详细描述,请参阅 此文件

使用私钥签名文档

签名文档意味着:使用私钥加密文档。

命令行

命令

gpg --armor -u 03DEC874738344206A1A7D31E07D9D14954C8DC5 --output document.pgp --sign document

# For automation inside a script:

exec 3> /tmp/status; echo 'password' | gpg --batch --yes --always-trust --status-fd 3 --passphrase-fd 0 --armor -u 03DEC874738344206A1A7D31E07D9D14954C8DC5 --output document.pgp --sign document; echo $?; exec 3>&-

然后使用公钥解密文档

gpg --output document.decrypted --decrypt document.pgp
gpg --output - --decrypt document.pgp

请注意,您可以使用与私钥关联的 子密钥 而不是私钥本身。

API

签名

static function signFile($inAPath, $inPrivateKeyFingerPrint, $inOptPassword=null, $inOptSignaturePath=null)
static function signString($inString, $inPrivateKeyFingerPrint, $inPassword=null, $inOptSignaturePath=null)

解密

static function decryptFile($inAbsolutePath, $inOptPassword=null, $inOptOutputFile=null)
static function decryptString($inString, $inOptPassword=null, $inOptOutputFile=null)

使用私钥进行清晰的文档签名

“清晰签名”文档意味着

  • 生成文档的散列(例如使用 SHA1)。
  • 使用私钥加密先前生成的散列。
  • 将加密的散列附加到文档的末尾(文档保持清晰)。

命令行

命令

gpg --armor -u 03DEC874738344206A1A7D31E07D9D14954C8DC5 --output document.pgp --clearsign document

# For automation inside a script:

exec 3> /tmp/status; echo 'password' | gpg --batch --yes --always-trust --status-fd 3 --passphrase-fd 0 --armor -u 03DEC874738344206A1A7D31E07D9D14954C8DC5 --output document.pgp --clearsign document; echo $?; exec 3>&-

验证签名

gpg --verify document.pgp

API

签名

static function clearSignFile($inPath, $inPrivateKeyFingerPrint, $inOptPassword=null, $inOptSignaturePath=null)
static function clearSignString($inString, $inPrivateKeyFingerPrint, $inPassword=null, $inOptSignaturePath=null)

验证签名

static function verifyClearSignedFile($inFilePath, &$outWarning)
static function verifyClearSignedString($inString, &$outWarning) {

创建分离的签名(使用私钥)

创建“分离的签名”意味着

  • 生成文档的散列(例如使用 SHA1)。
  • 使用私钥加密先前生成的散列。
  • 将加密的散列写入(指定的)文件。

请注意,“分离的签名”和“清晰签名”是相同的。区别在于“分离的签名”被放入单独的文件中,而“清晰签名”被附加到签名文档的末尾。

命令行

命令

gpg --armor -u 03DEC874738344206A1A7D31E07D9D14954C8DC5 --output document.PGP --detach-sign document

# For automation inside a script:

exec 3> /tmp/status; echo 'password' | gpg --batch --yes --always-trust --status-fd 3 --passphrase-fd 0 --armor -u 03DEC874738344206A1A7D31E07D9D14954C8DC5 --output document.pgp --detach-sign document; echo $?; exec 3>&-

验证签名

gpg --verify document.pgp document

API

签名

static function detachSignFile($inPath, $inPrivateKeyFingerPrint, $inOptPassword=null, $inOptSignaturePath=null)
static function detachSignString($inString, $inPrivateKeyFingerPrint, $inPassword=null, $inOptSignaturePath=null)

验证签名

static function verifyDetachedSignedFile($inSignatureFilePath, $inDocument, &$outWarning)
static function verifyDetachedSignedString($inSignature, $inDocument, &$outWarning)

使用公钥加密文档

请注意,在 GPG 术语中,使用私钥进行的加密称为“签名”(从技术角度讲,这是一种加密)。

命令行

命令

gpg --armor --output encrypted_file --encrypt --recipient 03DEC874738344206A1A7D31E07D9D14954C8DC5 document

# For automation inside a script:

exec 3> /tmp/status; gpg --batch --yes --status-fd 3 --always-trust --armor --output document.pgp --encrypt --recipient 03DEC874738344206A1A7D31E07D9D14954C8DC5 document; echo $?; exec 3>&-

使用私钥解密文件

gpg --output document --decrypt document.pgp

API

static function encryptAsymmetricFile($inInputPath, $inPublicKeyFingerPrint, $inOptOutputFile=null)
static function encryptAsymmetricString($inString, $inPublicKeyFingerPrint, $inOptOutputFile=null)

解密加密文件

请注意,该文档可能已被使用公钥或私钥(即签名)加密。

  • 如果文档已被公钥加密(可能是您的公钥),则需要私钥来解密它。
  • 如果文档已使用私钥签名,则需要公钥来解密它。

命令行

命令

gpg --output document --decrypt document.pgp

在脚本内部自动化

exec 3> /tmp/status; echo 'password' | gpg --batch --yes --status-fd 3 --passphrase-fd 0 --always-trust --output document --decrypt document.pgp; echo $?; exec 3>&-

API

static function decryptFile($inAbsolutePath, $inOptPassword=null, $inOptOutputFile=null)
static function decryptString($inString, $inOptPassword=null, $inOptOutputFile=null)

密钥管理

除了调用返回指纹的方法(getPublicKeyFingerPrintgetPrivateKeyFingerPrint)外,密钥通过其指纹进行识别。这确保了最大程度的安全,防止在指定密钥ID时可能发生的“副作用”。

API

static function getPublicKeyFingerPrint($inPublicKey)
static function getPrivateKeyFingerPrint($inPrivateKey)
static function isPrivateKeyPresent($inPrivateKeyFingerPrint)
static function isPublicKeyPresent($inPublicKeyFingerPrint)
static function removePrivateKey($inPrivateKeyFingerPrint)
static function removePublicKey($inPublicKeyFingerPrint)
static function importPrivateKey($inPrivateKeyPath)
static function importPublicKey($inPublicKeyPath)

其他方法

static function version()
static function checkVersion()

测试软件包

此软件包包含两对密钥

  • 一对其中私钥由密码保护。
  • 一对其中私钥没有保护。

这些密钥位于目录 tests/data

  • open.prv / open.pub:这对密钥没有保护。
  • protected.prv / protected.pub:这对密钥受保护。

导入这些密钥

cd tests/data
gpg --import open.prv; gpg --import open.pub; gpg --import protected.prv; gpg --import protected.pub

获取ID和指纹

对于公钥

gpg --batch --list-keys --fingerprint --with-colon

对于私钥

gpg --batch --list-secret-keys --fingerprint --with-colon

请参阅此文档以获取关于--with-colon选项输出的详细描述。

Perl脚本list-keys.pl可用于打印公钥列表。

gpg --list-keys --with-colon --fingerprint | perl list-keys.pl
gpg --list-secret-keys --with-colon --fingerprint | perl list-keys.pl

示例

gpg --list-secret-keys --with-colon --fingerprint | perl list-keys.pl

输出

6   sec E07D9D14954C8DC5 03DEC874738344206A1A7D31E07D9D14954C8DC5 0C185D728E760EC0 open key <ok@test.com>
6   sec 29A778386005B911 881C41F8B8FD138E86E7230929A778386005B911 6A492A01B27F4819 protected key <pk@test.com>

Whith

Column 1: the total number of columns for the current line.
Column 2: the type of key (pub: public, sec: secret).
Column 3: the UID of the key.
Column 4: the fingerprint of the key.
Column 5: the UID of the associated sub key.
Column 6: the ID of the key.

请注意

  • 每行的最后一字段可能有空格(例如:PHP coder <php_coder@php.com>)。
  • 一个密钥可能有多个子密钥。因此,一行可能有多于6个列。

创建私钥的打印备份

您可以生成您私钥的图形表示。这些表示可以打印在纸张上。

请注意,您可能不需要生成公钥的图形表示。实际上,公钥不需要保护。因此,您可以在任何地方制作公钥的副本。

安装数据矩阵工具

    $ sudo apt-get install  dmtx-utils

生成一个非常长的RSA密钥

    $ cat -n batch.txt
         1	%echo Generating a basic OpenPGP key
         2	Key-Type: RSA
         3	Key-Length: 8192
         4	Subkey-Type: RSA
         5	Subkey-Length: 8192
         6	Name-Real: Tester Long
         7	Name-Comment: This is for testing
         8	Name-Email: joe-long@foo.bar
         9	Expire-Date: 0
        10	Passphrase: abc
        11	# Do a commit here, so that we can later print "done" :-)
        12	%commit
        13	%echo done

    $ cat batch.txt | gpg --enable-large-rsa --batch --gen-key

查找生成的密钥的ID或指纹

通过ID

   $ gpg --list-keys
   sec   8192R/9BEF3AAC 2016-12-30
   uid                  Tester Long (This is for testing) <joe-long@foo.bar>
   ssb   8192R/3A57FB1C 2016-12-30

   $ gpg --export 9BEF3AAC > very-long-key.pub

   $ gpg --export-secret-key 9BEF3AAC > very-long-key.prv

通过指纹

    $ gpg --list-keys --fingerprint --with-colons
    pub:-:8192:1:FB9F45539BEF3AAC:2016-12-30:::-:Tester Long (This is for testing) <joe-long@foo.bar>::escaESCA:
    fpr:::::::::1335EF5C02BEF36A56DBA451FB9F45539BEF3AAC:
    sub:-:8192:1:1D4050C33A57FB1C:2016-12-30::::::esa:

然后生成表示私钥的图像

    $ gpg --export-secret-key 9BEF3AAC | paperkey --output-type raw | split -b 1500 - key-

    # Or:
    # gpg --export-secret-key 1335EF5C02BEF36A56DBA451FB9F45539BEF3AAC | paperkey --output-type raw | split -b 1500 - key-

    $ cat -n gen-images.sh
         1	#!/bin/bash
         2
         3	for K in key-*; do
         4	    dmtxwrite -e 8 $K > $K.png
         5	done

    $ ./gen-images.sh

    $ ls -1 *.png
    key-aa.png
    key-ab.png
    key-ac.png
    key-ad.png

表示私钥的图像列表是

key-aa.png

key-ab.png

key-ac.png

key-ad.png

从其图形表示中重新生成密钥

    $ cat -n gen-key.sh
         1	#!/bin/bash
         2
         3	rm -f key.prv
         4	for K in key-*.png; do
         5	    echo $K
         6	    dmtxread $K >> key.prv
         7	done

    $ ./gen-key.sh

    $ paperkey --pubring ~/.gnupg/pubring.gpg --secrets key.prv > restore.raw

    # Or:
    # paperkey --pubring very-long-key.pub --secrets key.prv > restore.raw

请注意,您需要公钥才能重新生成私钥!公钥可以存储在公钥环中,或存储在文件中。

将恢复的密钥与原始密钥进行比较

    $ gpg --list-packets restore.raw > f1

    $ gpg --list-packets very-long-key.prv > f2

    $ diff f1 f2

如果您尝试导入恢复的私钥

    $ gpg --import restore.raw
    gpg: key 9BEF3AAC: already in secret keyring
    gpg: Total number processed: 1
    gpg:       secret keys read: 1
    gpg:  secret keys unchanged: 1

使用原始私钥签名文档

    $ gpg -u 9BEF3AAC --sign gen-key.sh

从密钥环中删除原始私钥

    $ gpg --delete-secret-keys 9BEF3AAC

使用备份恢复私钥

    $ gpg --import restore.raw
    gpg: key 9BEF3AAC: secret key imported
    gpg: key 9BEF3AAC: "Tester Long (This is for testing) <joe-long@foo.bar>" not changed
    gpg: Total number processed: 1
    gpg:              unchanged: 1
    gpg:       secret keys read: 1
    gpg:   secret keys imported: 1

然后,确保恢复的私钥按预期工作

    $ gpg --output script.sh --decrypt gen-key.sh.gpg

    $ diff gen-key.sh script.sh

有用的链接

https://www.void.gr/kargig/blog/2013/12/02/creating-a-new-gpg-key-with-subkeys/

http://www.spywarewarrior.com/uiuc/gpg/gpg-com-4.htm