Skip to content

Commit 6283415

Browse files
committed
INCOMPATIBLE: Replace golang.org/x/crypto/openpgp
... with github.com/ProtonMail/go-crypto/openpgp x/crypto/openpgp now contains a stronger deprecation warning: > // Deprecated: this package is unsafe by design, and has numerous known security > // issues. It is not maintained, and should not be used. and points at github.com/ProtonMail/go-crypto/openpgp , so use that one. That is an INCOMPATIBLE change in that this implementation completely removes support for v3 signature packets (but we retain support for them with the other mechanism implementations). We can also remove the SigLifetimeSecs code because that is automatically enforced now (but we keep the expired-signature test). This currently adds an entirely new copy because ocicrypt still uses x/crypto, hopefully that can migrate as well. (But, still, this adds support for various algorithms that _are_ a long-term net new code.) Signed-off-by: Miloslav Trmač <mitr@redhat.com>
1 parent a2cf384 commit 6283415

174 files changed

Lines changed: 37799 additions & 51 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

image/go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ go 1.25.7
88
require (
99
dario.cat/mergo v1.0.2
1010
github.com/BurntSushi/toml v1.6.0
11+
github.com/ProtonMail/go-crypto v1.4.1
1112
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01
1213
github.com/containers/ocicrypt v1.3.1
1314
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467
@@ -39,7 +40,6 @@ require (
3940
go.etcd.io/bbolt v1.5.0
4041
go.podman.io/storage v1.63.0
4142
go.yaml.in/yaml/v3 v3.0.4
42-
golang.org/x/crypto v0.54.0
4343
golang.org/x/oauth2 v0.36.0
4444
golang.org/x/sync v0.22.0
4545
golang.org/x/term v0.45.0
@@ -53,6 +53,7 @@ require (
5353
github.com/cespare/xxhash/v2 v2.3.0 // indirect
5454
github.com/chzyer/readline v1.5.1 // indirect
5555
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
56+
github.com/cloudflare/circl v1.6.3 // indirect
5657
github.com/containerd/errdefs v1.0.0 // indirect
5758
github.com/containerd/errdefs/pkg v0.3.0 // indirect
5859
github.com/containerd/stargz-snapshotter/estargz v0.18.2 // indirect
@@ -96,6 +97,7 @@ require (
9697
go.opentelemetry.io/otel v1.44.0 // indirect
9798
go.opentelemetry.io/otel/metric v1.44.0 // indirect
9899
go.opentelemetry.io/otel/trace v1.44.0 // indirect
100+
golang.org/x/crypto v0.54.0 // indirect
99101
golang.org/x/net v0.56.0 // indirect
100102
golang.org/x/sys v0.47.0 // indirect
101103
golang.org/x/text v0.40.0 // indirect

image/go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk
66
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
77
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
88
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
9+
github.com/ProtonMail/go-crypto v1.4.1 h1:9RfcZHqEQUvP8RzecWEUafnZVtEvrBVL9BiF67IQOfM=
10+
github.com/ProtonMail/go-crypto v1.4.1/go.mod h1:e1OaTyu5SYVrO9gKOEhTc+5UcXtTUa+P3uLudwcgPqo=
911
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
1012
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
1113
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
@@ -23,6 +25,8 @@ github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
2325
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
2426
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
2527
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
28+
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
29+
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
2630
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
2731
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
2832
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=

image/signature/mechanism.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,7 @@ import (
99
"io"
1010
"strings"
1111

12-
// This code is used only to parse the data in an explicitly-untrusted
13-
// code path, where cryptography is not relevant. For now, continue to
14-
// use this frozen deprecated implementation. When mechanism_openpgp.go
15-
// migrates to another implementation, this should migrate as well.
16-
//lint:ignore SA1019 See above
17-
"golang.org/x/crypto/openpgp" //nolint:staticcheck
12+
"github.com/ProtonMail/go-crypto/openpgp"
1813
)
1914

2015
// SigningMechanism abstracts a way to sign binary blobs and verify their signatures.

image/signature/mechanism_openpgp.go

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,13 @@ import (
1010
"os"
1111
"path"
1212
"strings"
13-
"time"
1413

14+
"github.com/ProtonMail/go-crypto/openpgp"
1515
"go.podman.io/image/v5/signature/internal"
1616
"go.podman.io/storage/pkg/homedir"
17-
18-
// This is a fallback code; the primary recommendation is to use the gpgme mechanism
19-
// implementation, which is out-of-process and more appropriate for handling long-term private key material
20-
// than any Go implementation.
21-
// For this verify-only fallback, we haven't reviewed any of the
22-
// existing alternatives to choose; so, for now, continue to
23-
// use this frozen deprecated implementation.
24-
//lint:ignore SA1019 See above
25-
"golang.org/x/crypto/openpgp" //nolint:staticcheck
2617
)
2718

28-
// A GPG/OpenPGP signing mechanism, implemented using x/crypto/openpgp.
19+
// A GPG/OpenPGP signing mechanism, implemented using github.com/ProtonMail/go-crypto/openpgp.
2920
type openpgpSigningMechanism struct {
3021
keyring openpgp.EntityList
3122
}
@@ -155,18 +146,6 @@ func (m *openpgpSigningMechanism) Verify(unverifiedSignature []byte) (contents [
155146
if md.SignedBy == nil {
156147
return nil, "", internal.NewInvalidSignatureError(fmt.Sprintf("Key not found for key ID %x in signature", md.SignedByKeyId))
157148
}
158-
if md.Signature != nil {
159-
if md.Signature.SigLifetimeSecs != nil {
160-
expiry := md.Signature.CreationTime.Add(time.Duration(*md.Signature.SigLifetimeSecs) * time.Second)
161-
if time.Now().After(expiry) {
162-
return nil, "", internal.NewInvalidSignatureError(fmt.Sprintf("Signature expired on %s", expiry))
163-
}
164-
}
165-
} else if md.SignatureV3 == nil {
166-
// Coverage: If md.SignedBy != nil, the final md.UnverifiedBody.Read() either sets one of md.Signature or md.SignatureV3,
167-
// or sets md.SignatureError.
168-
return nil, "", internal.NewInvalidSignatureError("Unexpected openpgp.MessageDetails: neither Signature nor SignatureV3 is set")
169-
}
170149

171150
// Uppercase the fingerprint to be compatible with gpgme
172151
return content, strings.ToUpper(fmt.Sprintf("%x", md.SignedBy.Entity.PrimaryKey.Fingerprint)), nil

image/signature/mechanism_test.go

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ const (
1717
testGPGHomeDirectory = "./fixtures"
1818
)
1919

20-
// Many of the tests use two fixtures: V4 signature packets (*.signature), and V3 signature packets (*.signature-v3)
20+
// Many of the tests use two fixtures: V4 signature packets (*.signature), and V3 signature packets (*.signature-v3).
21+
// Note that V3 signature packets are not supported by openpgpSigningMechanism.
2122

2223
type fixtureVariant struct {
2324
path string
@@ -103,7 +104,9 @@ func TestNewGPGSigningMechanismInDirectory(t *testing.T) {
103104
defer mech.Close()
104105
for _, variant := range signatures {
105106
_, _, err := mech.Verify(variant.bytes)
106-
assert.NoError(t, err, variant.path)
107+
if !variant.isV3 { // V3 signatures might be entirely unsupported and rejected.
108+
assert.NoError(t, err, variant.path)
109+
}
107110
}
108111

109112
// If we use the default directory mechanism, GNUPGHOME is respected.
@@ -113,7 +116,9 @@ func TestNewGPGSigningMechanismInDirectory(t *testing.T) {
113116
defer mech.Close()
114117
for _, variant := range signatures {
115118
_, _, err := mech.Verify(variant.bytes)
116-
assert.NoError(t, err, variant.path)
119+
if !variant.isV3 { // V3 signatures might be entirely unsupported and rejected.
120+
assert.NoError(t, err, variant.path)
121+
}
117122
}
118123
}
119124

@@ -140,9 +145,13 @@ func TestNewEphemeralGPGSigningMechanism(t *testing.T) {
140145
// After import, the signature should validate.
141146
for _, variant := range signatures {
142147
content, signingFingerprint, err := mech.Verify(variant.bytes)
143-
require.NoError(t, err, variant.path)
144-
assert.Equal(t, []byte("This is not JSON\n"), content, variant.path)
145-
assert.Equal(t, TestKeyFingerprint, signingFingerprint, variant.path)
148+
if !variant.isV3 { // V3 signatures might be entirely unsupported and rejected.
149+
require.NoError(t, err, variant.path)
150+
}
151+
if err == nil {
152+
assert.Equal(t, []byte("This is not JSON\n"), content, variant.path)
153+
assert.Equal(t, TestKeyFingerprint, signingFingerprint, variant.path)
154+
}
146155
}
147156

148157
// Import of a key with a subkey
@@ -248,34 +257,46 @@ func TestGPGSigningMechanismVerify(t *testing.T) {
248257
require.NoError(t, err)
249258
defer mech.Close()
250259

260+
// For extra paranoia, test that we return nil data on error.
261+
251262
// Successful verification
252263
signatures := fixtureVariants(t, "./fixtures/invalid-blob.signature")
253264
for _, variant := range signatures {
254265
content, signingFingerprint, err := mech.Verify(variant.bytes)
255-
require.NoError(t, err, variant.path)
256-
assert.Equal(t, []byte("This is not JSON\n"), content, variant.path)
257-
assert.Equal(t, TestKeyFingerprint, signingFingerprint, variant.path)
266+
if !variant.isV3 { // V3 signatures might be entirely unsupported and rejected.
267+
require.NoError(t, err, variant.path)
268+
}
269+
if err == nil {
270+
assert.Equal(t, []byte("This is not JSON\n"), content, variant.path)
271+
assert.Equal(t, TestKeyFingerprint, signingFingerprint, variant.path)
272+
} else {
273+
assertSigningError(t, content, signingFingerprint, err)
274+
}
258275
}
259276
// Successful verification of a signature using a subkey
260277
signatures = fixtureVariants(t, "./fixtures/subkey.signature")
261278
for _, variant := range signatures {
262279
content, signingFingerprint, err := mech.Verify(variant.bytes)
263-
require.NoError(t, err, variant.path)
264-
assert.Equal(t, []byte(`{"critical":{"identity":{"docker-reference":"testing/manifest:latest"},"image":{"docker-manifest-digest":"sha256:20bf21ed457b390829cdbeec8795a7bea1626991fda603e0d01b4e7f60427e55"},"type":"atomic container signature"},"optional":{}}`), content, variant.path)
265-
if signingFingerprint != TestKeyFingerprintPrimaryWithSubkey {
266-
assert.Equal(t, TestKeyFingerprintSubkeyWithSubkey, signingFingerprint, variant.path)
267-
withLookup, ok := mech.(signingMechanismWithVerificationIdentityLookup)
268-
require.True(t, ok, variant.path)
269-
270-
primaryKey, err := withLookup.keyIdentityForVerificationKeyIdentity(signingFingerprint)
280+
if !variant.isV3 { // V3 signatures might be entirely unsupported and rejected.
271281
require.NoError(t, err, variant.path)
272-
signingFingerprint = primaryKey
273282
}
274-
assert.Equal(t, TestKeyFingerprintPrimaryWithSubkey, signingFingerprint, variant.path)
283+
if err == nil {
284+
assert.Equal(t, []byte(`{"critical":{"identity":{"docker-reference":"testing/manifest:latest"},"image":{"docker-manifest-digest":"sha256:20bf21ed457b390829cdbeec8795a7bea1626991fda603e0d01b4e7f60427e55"},"type":"atomic container signature"},"optional":{}}`), content, variant.path)
285+
if signingFingerprint != TestKeyFingerprintPrimaryWithSubkey {
286+
assert.Equal(t, TestKeyFingerprintSubkeyWithSubkey, signingFingerprint, variant.path)
287+
withLookup, ok := mech.(signingMechanismWithVerificationIdentityLookup)
288+
require.True(t, ok, variant.path)
289+
290+
primaryKey, err := withLookup.keyIdentityForVerificationKeyIdentity(signingFingerprint)
291+
require.NoError(t, err, variant.path)
292+
signingFingerprint = primaryKey
293+
}
294+
assert.Equal(t, TestKeyFingerprintPrimaryWithSubkey, signingFingerprint, variant.path)
295+
} else {
296+
assertSigningError(t, content, signingFingerprint, err)
297+
}
275298
}
276299

277-
// For extra paranoia, test that we return nil data on error.
278-
279300
// Completely invalid signature.
280301
content, signingFingerprint, err := mech.Verify([]byte{})
281302
assertSigningError(t, content, signingFingerprint, err)

vendor/github.com/ProtonMail/go-crypto/AUTHORS

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/ProtonMail/go-crypto/CONTRIBUTORS

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/ProtonMail/go-crypto/LICENSE

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/ProtonMail/go-crypto/PATENTS

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)