Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use key pair generated by openpgp in go

Tags:

go

rsa

openpgp

I'm trying to generate keypair with openpgp lib and when I want to test it by encrypting a test string, it returns the following error openpgp: invalid argument: cannot encrypt because no candidate hash functions are compiled in. (Wanted RIPEMD160 in this case.). However it works when I pass a public key exported from gpg.

Also I'm wondering how to encrypt the private key like gpg --generate-key does?

func main() {
    var e *openpgp.Entity
    var pubKey *bytes.Buffer

    e, _ = openpgp.NewEntity("testUser", "test", "[email protected]", nil)

    for _, id := range e.Identities {
        err := id.SelfSignature.SignUserId(id.UserId.Id, e.PrimaryKey, e.PrivateKey, nil)

        if err != nil {
            fmt.Println(err)
            return
        }
    }

    buf := new(bytes.Buffer)
    w, err := armor.Encode(buf, openpgp.PublicKeyType, nil)

    if err != nil {
        fmt.Println(err)
        return
    }

    e.Serialize(w)
    w.Close()
    pubKey = buf

    // Encrypting test with public key 
    entity, err := openpgp.ReadArmoredKeyRing(pubKey)

    if err != nil {
        fmt.Println(err)
        return
    }

    buf = new(bytes.Buffer)

    encoderWriter, err := armor.Encode(buf, "PGP MESSAGE", make(map[string]string))

    if err != nil {
        fmt.Println(err)
        return
    }

    encryptorWriter, err := openpgp.Encrypt(encoderWriter, entity, nil, nil, nil)

    if err != nil {
        fmt.Println(err)
        return
    }

    encryptorWriter.Write([]byte("hello world"))
    encryptorWriter.Close()
    encoderWriter.Close()

    fmt.Println(buf.String())
}
like image 763
Yok0 Avatar asked Oct 20 '25 23:10

Yok0


1 Answers

I had the exact same error.

TL; DR

  • It seems that it's an abandoned bug of the golang.org/x/crypto/openpgp package.
  • golang.org/x/crypto/openpgp package is frozen and deprecated. (= wontfix)
  • Use a patched fork package instead.
    • github.com/ProtonMail/go-crypto package @ GitHub

TS; DR

Since the official "golang.org/x/crypto/openpgp" package was frozen and deprecated, as long as we use the "golang.org/x/crypto/openpgp" package, it seems that the only current workaround is to either;

  1. Downgrade the Go version and the package, then blank import "_ golang.org/x/crypto/ripemd160" as @mh-cbon mentioned.
  2. Patch the rejected PR on your own. (Rejected due to the freezing of x/crypto/openpgp package)
    • Patch: https://github.com/golang/crypto/pull/128/files
    • PR: Use correct default hashes and default ciphers when no preferences given

But I had to implement an OpenPGP key pair generator on Go 1.16.6. Don't ask why...

So, my current alternative was to use the forked package. Which was one of the abounding forks that the Go team mentioned as a sample.

  • github.com/ProtonMail/go-crypto package @ GitHub
    1. go get github.com/ProtonMail/go-crypto
    2. Remove golang.org/x/crypto/openpgp from go.mod
    3. Replace all the "golang.org/x/crypto/openpgp" to "github.com/ProtonMail/go-crypto/openpgp" in the source code.
    4. go mod tidy

References

  1. "x/crypto/openpgp: mark as frozen and deprecated" | Issue #44226 | go | golang @ GitHub
  2. "x/crypto/openpgp: new entities cannot be encrypted to by default" | Issue #37646 | go | golang @ GitHub
  3. "x/crypto/openpgp: new entities cannot be encrypted to by default" | Issue #12153 | go | golang @ GitHub
like image 125
KEINOS Avatar answered Oct 23 '25 14:10

KEINOS



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!