Golang无需secring的pgp

huangapple go评论77阅读模式
英文:

Golang pgp without secring

问题

我有一个使用gpg密钥和密码提示来读取的应用程序。以下是我实现这个功能的方式(基于我在其他地方找到的一个示例):

func Decrypt(publicKeyring string, secretKeyring string, key string, password string) (string, error) {

    var entity *openpgp.Entity
    var entityList openpgp.EntityList

    keyringFileBuffer, err := os.Open(secretKeyring)
    if err != nil {
        return "", err
    }

    defer keyringFileBuffer.Close()
    entityList, err = openpgp.ReadKeyRing(keyringFileBuffer)
    if err != nil {
        return "", err
    }
    entity = entityList[0]

    passphraseByte := []byte(password)
    entity.PrivateKey.Decrypt(passphraseByte)
    for _, subkey := range entity.Subkeys {
        subkey.PrivateKey.Decrypt(passphraseByte)
    }

    dec, err := base64.StdEncoding.DecodeString(key)
    if err != nil {
        return "", err
    }

    // Decrypt it with the contents of the private key
    md, err := openpgp.ReadMessage(bytes.NewBuffer(dec), entityList, nil, nil)
    if err != nil {
        return "", err
    }
    bytes, err := ioutil.ReadAll(md.UnverifiedBody)
    if err != nil {
        return "", err
    }
    decStr := string(bytes)

    return decStr, nil

}

这里假设用户有一个KeyRing,它会被传递进来,而默认值是secring,像这样:

viper.SetDefault("gpgsecretkeyring", home+"/.gnupg/secring.gpg")

然而,有人报告说在Mac上使用该应用程序时遇到了问题,原因是他们不知道如何定义secring。

似乎较新版本的GnuPG已经弃用了secring。

https://www.gnupg.org/faq/whats-new-in-2.1.html#nosecring

我不知道如何使用golang.org/x/crypto/openpgp来读取密钥。是否有任何关于如何最佳实现的示例?

英文:

I have an app that uses gpg secret keys and prompts for a password to read it. Here's the way I do that (based on an example I found elsewhere:

func Decrypt(publicKeyring string, secretKeyring string, key string, password string) (string, error) {

	var entity *openpgp.Entity
	var entityList openpgp.EntityList

	keyringFileBuffer, err := os.Open(secretKeyring)
	if err != nil {
		return "", err
	}

	defer keyringFileBuffer.Close()
	entityList, err = openpgp.ReadKeyRing(keyringFileBuffer)
	if err != nil {
		return "", err
	}
	entity = entityList[0]

	passphraseByte := []byte(password)
	entity.PrivateKey.Decrypt(passphraseByte)
	for _, subkey := range entity.Subkeys {
		subkey.PrivateKey.Decrypt(passphraseByte)
	}

	dec, err := base64.StdEncoding.DecodeString(key)
	if err != nil {
		return "", err
	}

	// Decrypt it with the contents of the private key
	md, err := openpgp.ReadMessage(bytes.NewBuffer(dec), entityList, nil, nil)
	if err != nil {
		return "", err
	}
	bytes, err := ioutil.ReadAll(md.UnverifiedBody)
	if err != nil {
		return "", err
	}
	decStr := string(bytes)

	return decStr, nil

} 

The assumption made here is that the user has a KeyRin which is passed, and the default value for this is the secring, like so:

viper.SetDefault("gpgsecretkeyring", home+"/.gnupg/secring.gpg")

However,

I was getting reports that some users on macs were struggling to get the app working, and the reason was they didn't know how to define the secring.

It seems newer versions of GnuPG have deprecated the secring.

https://www.gnupg.org/faq/whats-new-in-2.1.html#nosecring

I have no idea how to read the secret key using golang.org/x/crypto/openpgp at this point. Are there any examples of the best way to do this?

答案1

得分: 1

GnuPG 2.1引入了两个更改:

  • secring.gpg合并到pubring.gpg文件中,您应该能够从pubring.gpg文件中读取秘密密钥。
  • 对于新安装,使用新的keybox格式,该格式目前(至少截至今天)不受go库支持。旧的安装(因此,具有旧格式的密钥环)不会自动合并。

如果您想使用GnuPG的密钥环,请直接调用GnuPG。如果您想使用Go的库,请不要操作GnuPG的密钥环文件,并存储您自己的密钥副本。

英文:

GnuPG 2.1 introduced two changes:

  • Merging the secring.gpg into the pubring.gpg file, you should be able to read the secret keys from the pubring.gpg file.
  • For new installations, the new keybox format is used, which is not supported by the go library (as of today, at least). Old installations (thus, with keyrings in the old format), are not automatically merged.

If you want to use GnuPG's keyring, directly call GnuPG. If you want to use Go's library, don't mess with GnuPG's keyring files and store your own copy of the keys.

答案2

得分: 0

我厌倦了处理这个问题,所以我决定更容易地通过os.Exec调用gpg -dq。示例代码如下:

package gpg

import (
	"bytes"
	"encoding/base64"
	"os/exec"
)

func Decrypt(key string) (string, error) {

	var cmd exec.Cmd
	var output bytes.Buffer

	gpgCmd, err := exec.LookPath("gpg")

	if err != nil {
		return "", err
	}

	cmd.Path = gpgCmd
	cmd.Args = []string{"--decrypt", "--quiet"}

	dec, err := base64.StdEncoding.DecodeString(key)
	if err != nil {
		return "", err
	}

	// 返回 dec(字节数组)的读取器接口
	d := bytes.NewReader(dec)

	// 将 d 管道连接到 gpg 命令的标准输入
	cmd.Stdin = d
	cmd.Stdout = &output

	if err := cmd.Run(); err != nil {
		return "", err
	}

	// 返回 gpg 命令的输出
	return output.String(), nil

}

以上是给定代码的翻译。

英文:

I got sick of dealing with this, so I've decided it's easier to just shell out to gpg -dq from the os.Exec. Sample:

package gpg

import (
	"bytes"
	"encoding/base64"
	"os/exec"
)

func Decrypt(key string) (string, error) {

	var cmd exec.Cmd
	var output bytes.Buffer

	gpgCmd, err := exec.LookPath("gpg")

	if err != nil {
		return "", err
	}

	cmd.Path = gpgCmd
	cmd.Args = []string{"--decrypt", "--quiet"}

	dec, err := base64.StdEncoding.DecodeString(key)
	if err != nil {
		return "", err
	}

	// return the reader interface for dec (byte array)
	d := bytes.NewReader(dec)

	// pipe d to gpg commands stdin
	cmd.Stdin = d
	cmd.Stdout = &output

	if err := cmd.Run(); err != nil {
		return "", err
	}

	// return the output from the gpg command
	return output.String(), nil

}

huangapple
  • 本文由 发表于 2017年8月28日 10:59:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/45911254.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定