A high-level OpenPGP library
GopenPGP V3 is a high-level OpenPGP library built on top of a fork of the golang crypto library.
Table of Contents
While GopenPGP V3 introduces a new API with significant enhancements, it is not backward compatible with GopenPGP V2. Although we recommend upgrading to V3 for the latest features and improvements, we continue to support GopenPGP V2. Our support includes ongoing bug fixes and minor feature updates to ensure stability and functionality for existing users.
GopenPGP V2 can be accessed/modified via the v2 branch of this repository.
To use GopenPGP with Go Modules just run
go get github.com/ProtonMail/gopenpgp/v3in your project folder.
Then, your code can include it as follows:
package main
import (
"fmt"
"github.com/ProtonMail/gopenpgp/v3/crypto"
)
func main() {
pgp := crypto.PGP()
}A full overview of the API can be found here: https://pkg.go.dev/github.com/ProtonMail/gopenpgp/v3.
A file of runnable examples can be found in crypto_example_test.go.
import "github.com/ProtonMail/gopenpgp/v3/crypto"
password := []byte("hunter2")
pgp := crypto.PGP()
// Encrypt data with a password
encHandle, err := pgp.Encryption().Password(password).New()
pgpMessage, err := encHandle.Encrypt([]byte("my message"))
armored, err := pgpMessage.ArmorBytes()
// Decrypt data with a password
decHandle, err := pgp.Decryption().Password(password).New()
decrypted, err := decHandle.Decrypt(armored, crypto.Armor)
myMessage := decrypted.Bytes()To encrypt with the latest OpenPGP standard (RFC 9580):
import "github.com/ProtonMail/gopenpgp/v3/profile"
// Use the latest OpenPGP standard (RFC 9580).
pgp := crypto.PGPWithProfile(profile.RFC9580())
// The RFC9580 profile uses Argon2 for protecting encrypted keys and
// messages encrypted using a passphrase, and uses AEAD for encryption
// (AES-256, OCB mode).
// Encrypt/Decrypt data with a password
... // See code snippet above.Use a custom or preset profile:
import "github.com/ProtonMail/gopenpgp/v3/profile"
// RFC4880 profile
pgp4880 := crypto.PGPWithProfile(profile.RFC4880())
// RFC9580 profile
pgpCryptoRefresh := crypto.PGPWithProfile(profile.RFC9580())…With signatures:
…Encrypt towards multiple recipients:
recipients, err := crypto.NewKeyRing(bobKeyPub)
err = recipients.AddKey(carolKeyPub)
// encrypt plain text message using a public key
encHandle, err := pgp.Encryption().
Recipients(recipients).
SigningKey(aliceKeyPriv).
New()
pgpMessage, err := encHandle.Encrypt([]byte("my message"))
armored, err := pgpMessage.ArmorBytes()
encHandle.ClearPrivateParams()Encrypt towards an (anonymous) recipient:
…Encrypt and decrypt large messages with the streaming API:
…Keys are generated with the GenerateKey function on the pgp handle.
…Encrypt (lock) and decrypt (unlock) a secret key:
password := []byte("password")
pgp := crypto.PGP()
// Encrypt key with password
lockedKey, err := pgp.LockKey(aliceKeyPriv, password)
// Decrypt key with password
unlockedKey, err := lockedKey.Unlock(password)Sign a plaintext with a private key and verify it with its public key using detached signatures:
pgp := crypto.PGP()
// ... See generating keys
signingMessage := []byte("message to sign")
signer, err := pgp.Sign().SigningKey(aliceKeyPriv).Detached().New()
signature, err := signer.Sign(signingMessage, crypto.Armor)
verifier, err := pgp.Verify().VerificationKey(aliceKeyPub).New()
verifyResult, err := verifier.VerifyDetached(signingMessage, signature, crypto.Armor)
if sigErr := verifyResult.SignatureError(); sigErr != nil {
// Handle sigErr
}
signer.ClearPrivateParams()Sign a plaintext with a private key and verify it with its public key using inline signatures:
pgp := crypto.PGP()
// ... See generating keys
signingMessage := []byte("message to sign")
signer, err := pgp.Sign().SigningKey(aliceKeyPriv).New()
signatureMessage, err := signer.Sign(signingMessage, crypto.Armor)
verifier, err := pgp.Verify().VerificationKey(aliceKeyPub).New()
verifyResult, err := verifier.VerifyInline(signatureMessage, crypto.Armor)
if sigErr := verifyResult.SignatureError(); sigErr != nil {
// Handle sigErr
}
// Access signed data with verifyResult.Bytes()
signer.ClearPrivateParams()…Split encrypted message into key packets and data packets
// Non-streaming
pgpMessage, err := encHandle.Encrypt(...)
keyPackets := pgpMessage.BinaryKeyPacket()
dataPackets := pgpMessage.BinaryDataPacket()
// Streaming
var keyPackets bytes.Buffer
var dataPackets bytes.Buffer
splitWriter := crypto.NewPGPSplitWriterKeyAndData(&keyPackets, &dataPackets)
ptWriter, _ := encHandle.EncryptingWriter(splitWriter, crypto.Bytes)
// ...
// Key packets are written to keyPackets while data packets are written to dataPacketsProduce encrypted detached signatures instead of embedded signatures:
…This library can be compiled with Gomobile too. First ensure you have a working installation of gomobile:
gomobile versionIn case this fails, install it with:
go get -u golang.org/x/mobile/cmd/gomobileThen ensure your path env var has gomobile's binary, and it is properly init-ed:
export PATH="$PATH:$GOPATH/bin"
gomobile initThen you must ensure that the Android or iOS frameworks are installed and the respective env vars set.
Finally, build the application
sh build.shThis script will build for both android and iOS at the same time, to filter one out you can comment out the line in the corresponding section.
No open issues yet, or sync has not completed.