keybase / go-crypto

[mirror] Go supplementary cryptography libraries
https://godoc.org/golang.org/x/crypto
BSD 3-Clause "New" or "Revised" License
50 stars 20 forks source link

Is there support encryption with multiple keys? #72

Open bailantaotao opened 6 years ago

bailantaotao commented 6 years ago

Hi there,

In GPG keychain, I can encrypt a message with multiple recipient public key, and it will return a PGP encrypted message. So that the valid user can decrypt the file.

But I tried in your opengpg package, it can encrypt message, but only one person can decrypt it with GPG keychain.

My step:

  1. Use GPG keychain export multiple users public key.
  2. Use your tool to encrypt a message with above public key and output to base64.
  3. Use GPG keychain CLI to decode the message. But got failed. The corresponding error message:
    
    echo ${ENCRYPTD_BY_OPENGPG_BASE64} | base64 -D | gpg -d`

gpg: encrypted with 4096-bit RSA key, ID 0A00AA00A000AA00, created 2016-02-27 "foo foo@bar.com" gpg: decryption failed: No secret key



What's step is wrong?
zapu commented 6 years ago

Hello, sorry for late reply.

Can you elaborate on the steps being done to encrypt the message?

go-crypto package supports encryption to multiple recipients, see here: https://github.com/keybase/go-crypto/blob/master/openpgp/write.go#L204-L209

dutchakdev commented 4 years ago

Hello, just code from my private project:

// Read PGP keys and create openpgp.EntityList with few keys
func readPublicKeys(keys []string) (openpgp.EntityList, error) {
    var entityLists openpgp.EntityList

    for _, key := range keys {
        entityList, err := openpgp.ReadArmoredKeyRing(strings.NewReader(key))
        if err != nil {
            return entityList, err
        }
        entityLists = append(entityLists, entityList[0])
    }

    return entityLists, nil
}

And you can use it with openpgp.Encrypt

Also my encrypt method wrapper for openpgp.Encrypt:

func encrypt(message string, entityList []*openpgp.Entity) (string, error) {
    buf := new(bytes.Buffer)
    w, err := openpgp.Encrypt(buf, entityList, nil, nil, nil)
    if err != nil {
        return "", err
    }
    _, err = w.Write([]byte(message))
    if err != nil {
        return "", err
    }
    err = w.Close()
    if err != nil {
        return "", err
    }

    output, err := ioutil.ReadAll(buf)
    if err != nil {
        return "", err
    }

    pubKeyBuf := bytes.NewBuffer(nil)
    pubKeyWriter, err := armor.Encode(pubKeyBuf, messageHeader, headers)
    if err != nil {
        return "", err
    }
    _, err = pubKeyWriter.Write(output)
    if err != nil {
        return "", err
    }
    err = pubKeyWriter.Close()
    if err != nil {
        return "", err
    }
    outputString := pubKeyBuf.String()

    return outputString, nil
}