Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
go-version: '1.22'
go-version: '1.23'
- uses: actions/checkout@v4
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.54.2
version: v1.64.5
4 changes: 2 additions & 2 deletions .github/workflows/ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ jobs:
runs-on: macos-latest

steps:
- name: Set up xcode 15.3.0
- name: Set up xcode 16.0.0
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: 15.3.0
xcode-version: 16.0.0
id: xcode

- name: Set up Go 1.x
Expand Down
7 changes: 7 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ issues:
- ST1003 # CamelCase variables; see constants/cipher.go
- missing output for example, go test can't validate it
- variable 'hasExpiredEntity' is only used in the if-statement
- G101
- Magic number
- param max has same name as predeclared identifier
- G115
- the methods of "signatureCollector"
exclude-rules:
- path: crypto/key_clear.go
text: "SA1019"
Expand All @@ -31,6 +36,8 @@ issues:
text: "Using the variable on range scope"
- path: crypto/sign_verify_test.go
text: "Using the variable on range scope"
- path: crypto/interop_test.go
text: "G101: Potential hardcoded credentials"

linters:
enable-all: true
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.4.0] – 2026-03-18
### Added
- `InsecureAllowAllKeyFlagsWhenMissing` profile option. Allows usage of keys without key flags.

### Changed
- Upgraded `go-crypto` fork to **v1.4.1**.

## [3.3.0] – 2025-05-23
### Added
- MaxDecompressedSize option to control the maximum size of decompressed messages.
Expand Down
2 changes: 1 addition & 1 deletion constants/version.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package constants

const Version = "3.3.0"
const Version = "3.4.0"
2 changes: 1 addition & 1 deletion crypto/encrypt_decrypt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,7 @@ func TestEncryptDecryptKey(t *testing.T) {
func TestEncryptCompressionApplied(t *testing.T) {
const numReplicas = 10
builder := strings.Builder{}
for i := 0; i < numReplicas; i++ {
for range numReplicas {
builder.WriteString(testMessage)
}
messageToEncrypt := builder.String()
Expand Down
19 changes: 10 additions & 9 deletions crypto/keyring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/ProtonMail/go-crypto/openpgp/ecdh"
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
Expand Down Expand Up @@ -121,11 +122,11 @@ func TestKeyIds(t *testing.T) {
}

func TestMultipleKeyRing(t *testing.T) {
assert.Exactly(t, 3, len(keyRingTestMultiple.entities))
assert.Len(t, keyRingTestMultiple.entities, 3)
assert.Exactly(t, 3, keyRingTestMultiple.CountEntities())
assert.Exactly(t, 3, keyRingTestMultiple.CountDecryptionEntities(testTime))

assert.Exactly(t, 3, len(keyRingTestMultiple.GetKeys()))
assert.Len(t, keyRingTestMultiple.GetKeys(), 3)

testKey, err := keyRingTestMultiple.GetKey(1)
if err != nil {
Expand All @@ -134,28 +135,28 @@ func TestMultipleKeyRing(t *testing.T) {
assert.Exactly(t, keyTestEC, testKey)

_, err = keyRingTestMultiple.GetKey(3)
assert.NotNil(t, err)
require.Error(t, err)

singleKeyRing, err := keyRingTestMultiple.FirstKey()
if err != nil {
t.Fatal("Expected no error while filtering the first key, got:", err)
}
assert.Exactly(t, 1, len(singleKeyRing.entities))
assert.Len(t, singleKeyRing.entities, 1)
assert.Exactly(t, 1, singleKeyRing.CountEntities())
assert.Exactly(t, 1, singleKeyRing.CountDecryptionEntities(testTime))
}

func TestSerializeParse(t *testing.T) {
serialized, err := keyRingTestMultiple.Serialize()
assert.Nil(t, err)
require.NoError(t, err)

parsed, err := NewKeyRingFromBinary(serialized)
assert.Nil(t, err)
require.NoError(t, err)

assert.Exactly(t, 3, len(parsed.GetKeys()))
assert.Len(t, parsed.GetKeys(), 3)
for i, parsedKey := range parsed.GetKeys() {
expectedKey, err := keyRingTestMultiple.GetKey(i)
assert.Nil(t, err)
require.NoError(t, err)
assert.Exactly(t, parsedKey.GetFingerprint(), expectedKey.GetFingerprint())
}
}
Expand All @@ -167,7 +168,7 @@ func TestClearPrivateKey(t *testing.T) {
}

for _, key := range keyRingCopy.GetKeys() {
assert.Nil(t, clearPrivateKey(key.entity.PrivateKey.PrivateKey))
require.NoError(t, clearPrivateKey(key.entity.PrivateKey.PrivateKey))
}

keys := keyRingCopy.GetKeys()
Expand Down
21 changes: 11 additions & 10 deletions crypto/message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestTextMessageEncryptionWithPassword(t *testing.T) {
Expand All @@ -32,7 +33,7 @@ func TestTextMessageEncryptionWithPassword(t *testing.T) {
}
sessionKey, ok := p.(*packet.SymmetricKeyEncrypted)
if ok {
assert.Equal(t, sessionKey.CipherFunc, packet.CipherAES256)
assert.Equal(t, packet.CipherAES256, sessionKey.CipherFunc)
foundSk = true
break
}
Expand All @@ -43,7 +44,7 @@ func TestTextMessageEncryptionWithPassword(t *testing.T) {
// Decrypt data with wrong password
decryptorWrong, _ := testPGP.Decryption().Password([]byte("Wrong password")).New()
_, err = decryptorWrong.Decrypt(encrypted.Bytes(), Bytes)
assert.NotNil(t, err)
require.Error(t, err)

// Decrypt data with the good password
decryptor, _ := testPGP.Decryption().Password(testSymmetricKey).New()
Expand All @@ -67,7 +68,7 @@ func TestBinaryMessageEncryptionWithPassword(t *testing.T) {
// Decrypt data with wrong password
decryptorWrong, _ := testPGP.Decryption().Password([]byte("Wrong password")).New()
_, err = decryptorWrong.Decrypt(encrypted.Bytes(), Bytes)
assert.NotNil(t, err)
require.Error(t, err)

// Decrypt data with the good password
decryptor, _ := testPGP.Decryption().Password(testSymmetricKey).New()
Expand Down Expand Up @@ -305,7 +306,7 @@ func TestSHA1SignedMessageDecryption(t *testing.T) {

func TestMultipleKeyMessageEncryption(t *testing.T) {
var message = []byte("plain text")
assert.Exactly(t, 3, len(keyRingTestMultiple.entities))
assert.Len(t, keyRingTestMultiple.entities, 3)

encryptor, _ := testPGP.Encryption().Recipients(keyRingTestMultiple).SigningKeys(keyRingTestPrivate).New()
ciphertext, err := encryptor.Encrypt(message)
Expand All @@ -317,7 +318,7 @@ func TestMultipleKeyMessageEncryption(t *testing.T) {
// followed by a single symmetrically encrypted data packet (tag 18)
var p packet.Packet
packets := packet.NewReader(bytes.NewReader(ciphertext.Bytes()))
for i := 0; i < 3; i++ {
for range 3 {
if p, err = packets.Next(); err != nil {
t.Fatal(err.Error())
}
Expand Down Expand Up @@ -349,15 +350,15 @@ func TestMultipleKeyMessageEncryption(t *testing.T) {

func TestMessageGetEncryptionKeyIDs(t *testing.T) {
var message = []byte("plain text")
assert.Exactly(t, 3, len(keyRingTestMultiple.entities))
assert.Len(t, keyRingTestMultiple.entities, 3)

encryptor, _ := testPGP.Encryption().Recipients(keyRingTestMultiple).SigningKeys(keyRingTestPrivate).New()
ciphertext, err := encryptor.Encrypt(message)
if err != nil {
t.Fatal("Expected no error when encrypting, got:", err)
}
ids, ok := ciphertext.EncryptionKeyIDs()
assert.Exactly(t, 3, len(ids))
assert.Len(t, ids, 3)
assert.True(t, ok)
encKey, ok := keyRingTestMultiple.entities[0].EncryptionKey(time.Now(), nil)
assert.True(t, ok)
Expand All @@ -371,7 +372,7 @@ func TestMessageGetHexGetEncryptionKeyIDs(t *testing.T) {
}

ids, ok := ciphertext.HexEncryptionKeyIDs()
assert.Exactly(t, 2, len(ids))
assert.Len(t, ids, 2)
assert.True(t, ok)

assert.Exactly(t, "76ad736fa7e0e83c", ids[0])
Expand All @@ -388,7 +389,7 @@ func TestMessageGetSignatureKeyIDs(t *testing.T) {
}

ids, ok := SignatureKeyIDs(signature)
assert.Exactly(t, 1, len(ids))
assert.Len(t, ids, 1)
assert.True(t, ok)
signingKey, ok := keyRingTestPrivate.entities[0].SigningKey(time.Now(), nil)
assert.True(t, ok)
Expand All @@ -402,7 +403,7 @@ func TestMessageGetHexSignatureKeyIDs(t *testing.T) {
}

ids, ok := ciphertext.HexSignatureKeyIDs()
assert.Exactly(t, 2, len(ids))
assert.Len(t, ids, 2)
assert.True(t, ok)

assert.Exactly(t, "3eb6259edf21df24", ids[0])
Expand Down
17 changes: 9 additions & 8 deletions crypto/sessionkey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/ProtonMail/gopenpgp/v3/constants"
"github.com/ProtonMail/gopenpgp/v3/profile"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

var testSessionKey *SessionKey
Expand Down Expand Up @@ -81,7 +82,7 @@ func TestSymmetricKeyPacket(t *testing.T) {
decHandle, _ := testPGP.Decryption().Password([]byte("Wrong password")).New()
wrongSymmetricKey, err := decHandle.DecryptSessionKey(keyPacket)
if err != nil {
assert.EqualError(t, err, "gopenpgp: unable to decrypt any packet")
require.EqualError(t, err, "gopenpgp: unable to decrypt any packet")
} else {
assert.NotEqual(t, testSessionKey, wrongSymmetricKey)
}
Expand Down Expand Up @@ -134,7 +135,7 @@ func TestDataPacketEncryption(t *testing.T) {
}
decryptor, _ := testPGP.Decryption().SessionKey(wrongKey).New()
_, err = decryptor.Decrypt(pgpMessage.BinaryDataPacket(), Bytes)
assert.NotNil(t, err)
require.Error(t, err)

// Decrypt data with the good session key
decryptor, _ = testPGP.Decryption().SessionKey(testSessionKey).New()
Expand All @@ -145,7 +146,7 @@ func TestDataPacketEncryption(t *testing.T) {
assert.Exactly(t, message, decrypted.Bytes())

// Encrypt session key
assert.Exactly(t, 3, len(keyRingTestMultiple.entities))
assert.Len(t, keyRingTestMultiple.entities, 3)
encryptor, _ = testPGP.Encryption().Recipients(keyRingTestMultiple).New()
keyPackets, err := encryptor.EncryptSessionKey(testSessionKey)
if err != nil {
Expand All @@ -167,7 +168,7 @@ func TestDataPacketEncryption(t *testing.T) {
}
ids, ok := pgpMessage.EncryptionKeyIDs()
assert.True(t, ok)
assert.Exactly(t, 3, len(ids))
assert.Len(t, ids, 3)

// Test if final decryption succeeds
decryptor, _ = testPGP.Decryption().DecryptionKeys(keyRingTestPrivate).New()
Expand Down Expand Up @@ -239,7 +240,7 @@ func TestDataPacketEncryptionAndSignature(t *testing.T) {
}
decryptor, _ := testPGP.Decryption().SessionKey(wrongKey).New()
_, err = decryptor.Decrypt(pgpMessage.BinaryDataPacket(), Bytes)
assert.NotNil(t, err)
require.Error(t, err)

// Decrypt data with the good session key
decryptor, _ = testPGP.Decryption().SessionKey(testSessionKey).New()
Expand Down Expand Up @@ -276,7 +277,7 @@ func TestDataPacketEncryptionAndSignature(t *testing.T) {
assert.Exactly(t, message, decrypted.Bytes())

// Encrypt session key
assert.Exactly(t, 3, len(keyRingTestMultiple.entities))
assert.Len(t, keyRingTestMultiple.entities, 3)
encryptor, _ = testPGP.Encryption().Recipients(keyRingTestMultiple).New()
keyPacket, err := encryptor.EncryptSessionKey(testSessionKey)
if err != nil {
Expand All @@ -298,7 +299,7 @@ func TestDataPacketEncryptionAndSignature(t *testing.T) {
}
ids, ok := pgpMessage.EncryptionKeyIDs()
assert.True(t, ok)
assert.Exactly(t, 3, len(ids))
assert.Len(t, ids, 3)

// Test if final decryption & verification succeeds
decryptor, _ = testPGP.Decryption().DecryptionKeys(keyRingTestPrivate).VerificationKeys(keyRingTestPublic).New()
Expand Down Expand Up @@ -345,7 +346,7 @@ func TestMDCFailDecryption(t *testing.T) {

decryptor, _ := testPGP.Decryption().SessionKey(sessionKey).New()
_, err = decryptor.Decrypt(pgpMessage.BinaryDataPacket(), Bytes)
assert.NotNil(t, err)
assert.Error(t, err)
}

func TestAsymmetricKeyPacketDecryptionFailure(t *testing.T) {
Expand Down
6 changes: 0 additions & 6 deletions crypto/signature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,6 @@ func Test_KeyRing_GetVerifiedSignatureTimestampSuccess(t *testing.T) {
t.Fatal(err)
}
actualTime := verificationResult.SignatureCreationTime()
if err != nil {
t.Errorf("Got an error while parsing the signature creation time: %v", err)
}
if timeLocal != actualTime {
t.Errorf("Expected creation time to be %d, got %d", timeLocal, actualTime)
}
Expand Down Expand Up @@ -226,9 +223,6 @@ func Test_KeyRing_GetVerifiedSignatureWithTwoKeysTimestampSuccess(t *testing.T)
}
actualTime := verificationResult.SignatureCreationTime()
otherTime := verificationResult.Signatures[1].Signature.CreationTime.Unix()
if err != nil {
t.Errorf("Got an error while parsing the signature creation time: %v", err)
}

if time2 != otherTime {
t.Errorf("Expected creation time to be %d, got %d", otherTime, time2)
Expand Down
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
module github.com/ProtonMail/gopenpgp/v3

go 1.22.0
go 1.23.0

require (
github.com/ProtonMail/go-crypto v1.3.0
github.com/ProtonMail/go-crypto v1.4.1
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f
github.com/stretchr/testify v1.10.0
)

require (
github.com/cloudflare/circl v1.6.0 // indirect
github.com/cloudflare/circl v1.6.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.2.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/crypto v0.33.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/crypto v0.41.0 // indirect
golang.org/x/sys v0.35.0 // indirect
golang.org/x/text v0.28.0 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading
Loading