4

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", "test@test.test", 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())
}
Yok0
  • 121
  • 1
  • 9
  • 2
    you have to import it using a blank import `_ "golang.org/x/crypto/ripemd160"` –  Mar 23 '21 at 16:28
  • Weird, the doc says that ripemd160 is deprecated. Opengpg isn't supposed to use sha256 by default? – Yok0 Mar 24 '21 at 09:20

1 Answers1

3

I had the exact same error.

TL; DR

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)

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
KEINOS
  • 1,050
  • 2
  • 13
  • 32
  • 1
    After some research, I also went with the proton's fork but forgot to update my post. Thanks for you're clear and helpful response! – Yok0 Aug 09 '21 at 14:43