Merge pull request #51411 from tonistiigi/update-buildkit-v0.26.0-rc1

vendor: update buildkit v0.26.0-rc2
This commit is contained in:
Sebastiaan van Stijn
2025-11-12 01:05:05 +01:00
committed by GitHub
446 changed files with 56756 additions and 6661 deletions

View File

@@ -194,7 +194,7 @@ func (is *Source) resolveRemote(ctx context.Context, ref string, platform *ocisp
}
// ResolveImageConfig returns image config for an image
func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt sourceresolver.Opt, sm *session.Manager, g session.Group) (digest.Digest, []byte, error) {
func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt sourceresolver.Opt, sm *session.Manager, jobCtx solver.JobContext) (digest.Digest, []byte, error) {
if opt.ImageOpt == nil {
return "", nil, fmt.Errorf("can only resolve an image: %v, opt: %v", ref, opt)
}
@@ -206,9 +206,17 @@ func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt source
if err != nil {
return "", nil, err
}
var p *ocispec.Platform
if opt.ImageOpt != nil && opt.ImageOpt.Platform != nil {
p = opt.ImageOpt.Platform
}
var g session.Group
if jobCtx != nil {
g = jobCtx.Session()
}
switch resolveMode {
case resolver.ResolveModeForcePull:
return is.resolveRemote(ctx, ref, opt.Platform, sm, g)
return is.resolveRemote(ctx, ref, p, sm, g)
// TODO: pull should fallback to local in case of failure to allow offline behavior
// the fallback doesn't work currently
/*
@@ -226,9 +234,9 @@ func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt source
case resolver.ResolveModePreferLocal:
img, err := is.resolveLocal(ref)
if err == nil {
if opt.Platform != nil && !platformMatches(img, opt.Platform) {
if p != nil && !platformMatches(img, p) {
log.G(ctx).WithField("ref", ref).Debugf("Requested build platform %s does not match local image platform %s, checking remote",
path.Join(opt.Platform.OS, opt.Platform.Architecture, opt.Platform.Variant),
path.Join(p.OS, p.Architecture, p.Variant),
path.Join(img.OS, img.Architecture, img.Variant),
)
} else {
@@ -236,7 +244,7 @@ func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt source
}
}
// fallback to remote
return is.resolveRemote(ctx, ref, opt.Platform, sm, g)
return is.resolveRemote(ctx, ref, p, sm, g)
}
// should never happen
return "", nil, fmt.Errorf("builder cannot resolve image %s: invalid mode %q", ref, opt.ImageOpt.ResolveMode)
@@ -337,7 +345,7 @@ func (p *puller) resolveLocal() {
})
}
func (p *puller) resolve(ctx context.Context, g session.Group) error {
func (p *puller) resolve(ctx context.Context, jobCtx solver.JobContext) error {
_, err := p.g.Do(ctx, "", func(ctx context.Context) (_ struct{}, retErr error) {
resolveProgressDone := oneOffProgress(ctx, "resolve "+p.src.Reference.String())
defer func() {
@@ -348,6 +356,10 @@ func (p *puller) resolve(ctx context.Context, g session.Group) error {
if err != nil {
return struct{}{}, err
}
var g session.Group
if jobCtx != nil {
g = jobCtx.Session()
}
if p.desc.Digest == "" && p.config == nil {
origRef, desc, err := p.resolver(g).Resolve(ctx, ref.String())
@@ -370,11 +382,11 @@ func (p *puller) resolve(ctx context.Context, g session.Group) error {
return struct{}{}, err
}
_, dt, err := p.is.ResolveImageConfig(ctx, refWithDigest.String(), sourceresolver.Opt{
Platform: &p.platform,
ImageOpt: &sourceresolver.ResolveImageOpt{
ResolveMode: p.src.ResolveMode.String(),
Platform: &p.platform,
},
}, p.sm, g)
}, p.sm, jobCtx)
if err != nil {
return struct{}{}, err
}
@@ -387,7 +399,7 @@ func (p *puller) resolve(ctx context.Context, g session.Group) error {
return err
}
func (p *puller) CacheKey(ctx context.Context, g session.Group, index int) (string, string, solver.CacheOpts, bool, error) {
func (p *puller) CacheKey(ctx context.Context, jobCtx solver.JobContext, index int) (string, string, solver.CacheOpts, bool, error) {
p.resolveLocal()
if p.desc.Digest != "" && index == 0 {
@@ -406,7 +418,7 @@ func (p *puller) CacheKey(ctx context.Context, g session.Group, index int) (stri
return k, k, nil, true, nil
}
if err := p.resolve(ctx, g); err != nil {
if err := p.resolve(ctx, jobCtx); err != nil {
return "", "", nil, false, err
}
@@ -451,10 +463,10 @@ func (p *puller) getRef(ctx context.Context, diffIDs []layer.DiffID, opts ...cac
}, parent, opts...)
}
func (p *puller) Snapshot(ctx context.Context, g session.Group) (cache.ImmutableRef, error) {
func (p *puller) Snapshot(ctx context.Context, jobCtx solver.JobContext) (cache.ImmutableRef, error) {
p.resolveLocal()
if len(p.config) == 0 {
if err := p.resolve(ctx, g); err != nil {
if err := p.resolve(ctx, jobCtx); err != nil {
return nil, err
}
}
@@ -504,6 +516,11 @@ func (p *puller) Snapshot(ctx context.Context, g session.Group) (cache.Immutable
<-progressDone
}()
var g session.Group
if jobCtx != nil {
g = jobCtx.Session()
}
fetcher, err := p.resolver(g).Fetcher(ctx, p.ref)
if err != nil {
stopProgress()

View File

@@ -12,6 +12,8 @@ import (
"github.com/moby/buildkit/cache/remotecache"
registryremotecache "github.com/moby/buildkit/cache/remotecache/registry"
v1 "github.com/moby/buildkit/cache/remotecache/v1"
cacheimporttypes "github.com/moby/buildkit/cache/remotecache/v1/types"
"github.com/moby/buildkit/session"
"github.com/moby/buildkit/solver"
"github.com/moby/buildkit/worker"
@@ -83,7 +85,7 @@ func (li *localImporter) importInlineCache(ctx context.Context, dt []byte, cc so
return nil
}
var config v1.CacheConfig
var config cacheimporttypes.CacheConfig
if err := json.Unmarshal(img.Cache, &config.Records); err != nil {
return err
}
@@ -113,7 +115,7 @@ func (li *localImporter) importInlineCache(ctx context.Context, dt []byte, cc so
Descriptor: desc,
Provider: &emptyProvider{},
}
config.Layers = append(config.Layers, v1.CacheLayer{
config.Layers = append(config.Layers, cacheimporttypes.CacheLayer{
Blob: dgst,
ParentIndex: i - 1,
})

View File

@@ -70,16 +70,17 @@ type LayerAccess interface {
// Opt defines a structure for creating a worker.
type Opt struct {
ID string
Labels map[string]string
GCPolicy []client.PruneInfo
Executor executor.Executor
Snapshotter snapshot.Snapshotter
ContentStore *containerdsnapshot.Store
CacheManager cache.Manager
LeaseManager *leaseutil.Manager
GarbageCollect func(context.Context) (gc.Stats, error)
ImageSource *imageadapter.Source
ID string
Labels map[string]string
GCPolicy []client.PruneInfo
Executor executor.Executor
Snapshotter snapshot.Snapshotter
ContentStore *containerdsnapshot.Store
CacheManager cache.Manager
LeaseManager *leaseutil.Manager
GarbageCollect func(context.Context) (gc.Stats, error)
ImageSource *imageadapter.Source
DownloadManager *xfer.LayerDownloadManager
V2MetadataService distmetadata.V2MetadataService
Transport nethttp.RoundTripper
@@ -94,6 +95,8 @@ type Opt struct {
type Worker struct {
Opt
SourceManager *source.Manager
GitSource *git.Source
HTTPSource *http.Source
}
var _ interface {
@@ -141,6 +144,8 @@ func NewWorker(opt Opt) (*Worker, error) {
return &Worker{
Opt: opt,
SourceManager: sm,
GitSource: gs,
HTTPSource: hs,
}, nil
}
@@ -241,13 +246,19 @@ func (w *Worker) LoadRef(ctx context.Context, id string, hidden bool) (cache.Imm
return w.CacheManager().Get(ctx, id, nil, opts...)
}
func (w *Worker) ResolveSourceMetadata(ctx context.Context, op *pb.SourceOp, opt sourceresolver.Opt, sm *session.Manager, g session.Group) (*sourceresolver.MetaResponse, error) {
func (w *Worker) ResolveSourceMetadata(ctx context.Context, op *pb.SourceOp, opt sourceresolver.Opt, sm *session.Manager, jobCtx solver.JobContext) (*sourceresolver.MetaResponse, error) {
if opt.SourcePolicies != nil {
return nil, errors.New("source policies can not be set for worker")
}
var p *ocispec.Platform
if imgOpt := opt.ImageOpt; imgOpt != nil && imgOpt.Platform != nil {
p = imgOpt.Platform
} else if ociOpt := opt.OCILayoutOpt; ociOpt != nil && ociOpt.Platform != nil {
p = ociOpt.Platform
}
var platform *pb.Platform
if p := opt.Platform; p != nil {
if p != nil {
platform = &pb.Platform{
Architecture: p.Architecture,
OS: p.OS,
@@ -266,10 +277,19 @@ func (w *Worker) ResolveSourceMetadata(ctx context.Context, op *pb.SourceOp, opt
if opt.ImageOpt == nil {
opt.ImageOpt = &sourceresolver.ResolveImageOpt{}
}
dgst, config, err := w.ImageSource.ResolveImageConfig(ctx, idt.Reference.String(), opt, sm, g)
if p != nil {
opt.ImageOpt.Platform = p
}
if opt.ImageOpt.AttestationChain {
return nil, errors.Errorf("resolving image attestation chain requires containerd image store support in dockerd")
}
dgst, config, err := w.ImageSource.ResolveImageConfig(ctx, idt.Reference.String(), opt, sm, jobCtx)
if err != nil {
return nil, err
}
if opt.ImageOpt.NoConfig {
config = nil
}
return &sourceresolver.MetaResponse{
Op: op,
Image: &sourceresolver.ResolveImageResponse{
@@ -277,6 +297,44 @@ func (w *Worker) ResolveSourceMetadata(ctx context.Context, op *pb.SourceOp, opt
Config: config,
},
}, nil
case *git.GitIdentifier:
if w.GitSource == nil {
return nil, errors.New("git source is not supported")
}
mdOpt := git.MetadataOpts{}
if opt.GitOpt != nil {
mdOpt.ReturnObject = opt.GitOpt.ReturnObject
}
md, err := w.GitSource.ResolveMetadata(ctx, idt, sm, jobCtx, mdOpt)
if err != nil {
return nil, err
}
return &sourceresolver.MetaResponse{
Op: op,
Git: &sourceresolver.ResolveGitResponse{
Checksum: md.Checksum,
Ref: md.Ref,
CommitChecksum: md.CommitChecksum,
CommitObject: md.CommitObject,
TagObject: md.TagObject,
},
}, nil
case *http.HTTPIdentifier:
if w.HTTPSource == nil {
return nil, errors.New("http source is not supported")
}
md, err := w.HTTPSource.ResolveMetadata(ctx, idt, sm, jobCtx)
if err != nil {
return nil, err
}
return &sourceresolver.MetaResponse{
Op: op,
HTTP: &sourceresolver.ResolveHTTPResponse{
Digest: md.Digest,
Filename: md.Filename,
LastModified: md.LastModified,
},
}, nil
}
return &sourceresolver.MetaResponse{
@@ -308,8 +366,8 @@ func (w *Worker) ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge, sm *se
}
// ResolveImageConfig returns image config for an image
func (w *Worker) ResolveImageConfig(ctx context.Context, ref string, opt sourceresolver.Opt, sm *session.Manager, g session.Group) (digest.Digest, []byte, error) {
return w.ImageSource.ResolveImageConfig(ctx, ref, opt, sm, g)
func (w *Worker) ResolveImageConfig(ctx context.Context, ref string, opt sourceresolver.Opt, sm *session.Manager, jobCtx solver.JobContext) (digest.Digest, []byte, error) {
return w.ImageSource.ResolveImageConfig(ctx, ref, opt, sm, jobCtx)
}
// DiskUsage returns disk usage report

41
go.mod
View File

@@ -55,7 +55,7 @@ require (
github.com/miekg/dns v1.1.66
github.com/mistifyio/go-zfs/v3 v3.0.1
github.com/mitchellh/copystructure v1.2.0
github.com/moby/buildkit v0.25.2
github.com/moby/buildkit v0.26.0-rc2
github.com/moby/docker-image-spec v1.3.1
github.com/moby/go-archive v0.1.0
github.com/moby/ipvs v1.1.0
@@ -118,14 +118,15 @@ require (
)
require (
cloud.google.com/go v0.117.0 // indirect
cloud.google.com/go/auth v0.13.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect
cloud.google.com/go/longrunning v0.6.2 // indirect
cloud.google.com/go v0.121.6 // indirect
cloud.google.com/go/auth v0.16.5 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/longrunning v0.6.7 // indirect
cyphar.com/go-pathrs v0.2.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0 // indirect
github.com/ProtonMail/go-crypto v1.3.0 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 // indirect
@@ -144,15 +145,16 @@ require (
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cilium/ebpf v0.17.3 // indirect
github.com/cloudflare/circl v1.6.0 // indirect
github.com/container-storage-interface/spec v1.5.0 // indirect
github.com/containerd/accelerated-container-image v1.3.0 // indirect
github.com/containerd/console v1.0.5 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/go-cni v1.1.13 // indirect
github.com/containerd/go-runc v1.1.0 // indirect
github.com/containerd/nydus-snapshotter v0.15.2 // indirect
github.com/containerd/nydus-snapshotter v0.15.4 // indirect
github.com/containerd/plugin v1.0.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.17.0 // indirect
github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containernetworking/cni v1.3.0 // indirect
github.com/containernetworking/plugins v1.8.0 // indirect
@@ -167,15 +169,15 @@ require (
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gofrs/flock v0.12.1 // indirect
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/gofrs/flock v0.13.0 // indirect
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/certificate-transparency-go v1.1.4 // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/google/certificate-transparency-go v1.3.2 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.14.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
@@ -185,12 +187,14 @@ require (
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hiddeco/sshsig v0.2.0 // indirect
github.com/in-toto/in-toto-golang v0.9.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmoiron/sqlx v1.3.3 // indirect
github.com/klauspost/compress v1.18.1 // indirect
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/policy-helpers v0.0.0-20251105011237-bcaa71c99f14 // indirect
github.com/moby/sys/capability v0.4.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
@@ -206,7 +210,7 @@ require (
github.com/prometheus/procfs v0.16.1 // indirect
github.com/sasha-s/go-deadlock v0.3.5 // indirect
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.6.0 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.9.1 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
github.com/spdx/tools-golang v0.5.5 // indirect
github.com/stretchr/testify v1.11.1 // indirect
@@ -241,11 +245,10 @@ require (
golang.org/x/crypto v0.43.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/tools v0.37.0 // indirect
google.golang.org/api v0.214.0 // indirect
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect; TODO(thaJeztah): should we keep this one aligned with the other google.golang.org/genproto/xxx modules?
google.golang.org/api v0.248.0 // indirect
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect; TODO(thaJeztah): should we keep this one aligned with the other google.golang.org/genproto/xxx modules?
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
tags.cncf.io/container-device-interface/specs-go v1.0.0 // indirect
)

103
go.sum
View File

@@ -1,19 +1,19 @@
cloud.google.com/go v0.16.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.117.0 h1:Z5TNFfQxj7WG2FgOGX1ekC5RiXrYgms6QscOm32M/4s=
cloud.google.com/go v0.117.0/go.mod h1:ZbwhVTb1DBGt2Iwb3tNO6SEK4q+cplHZmLWH+DelYYc=
cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs=
cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q=
cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU=
cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
cloud.google.com/go v0.121.6 h1:waZiuajrI28iAf40cWgycWNgaXPO06dupuS+sgibK6c=
cloud.google.com/go v0.121.6/go.mod h1:coChdst4Ea5vUpiALcYKXEpR1S9ZgXbhEzzMcMR66vI=
cloud.google.com/go/auth v0.16.5 h1:mFWNQ2FEVWAliEQWpAdH80omXFokmrnbDhUS9cBywsI=
cloud.google.com/go/auth v0.16.5/go.mod h1:utzRfHMP+Vv0mpOkTRQoWD2q3BatTOoWbA7gCc2dUhQ=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA=
cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw=
cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA=
cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY=
cloud.google.com/go/iam v1.5.2 h1:qgFRAGEmd8z6dJ/qyEchAuL9jpswyODjA2lS+w234g8=
cloud.google.com/go/iam v1.5.2/go.mod h1:SE1vg0N81zQqLzQEwxL2WI6yhetBdbNQuTvIKCSkUHE=
cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc=
cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA=
cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc=
cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI=
cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE=
cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY=
code.cloudfoundry.org/clock v1.37.0 h1:7e/FmrQ8f3cJW1aR4jhKWaEimBp5Ub39dOeNXQHq8HM=
code.cloudfoundry.org/clock v1.37.0/go.mod h1:9bvV2riUok6o34gOGGVIkX1v37wwsZbuSCBx8Y4laL0=
cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8=
@@ -22,20 +22,20 @@ dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 h1:Hr5FTipp7SL07o2FvoVOX9HRiRH3CR3Mj8pxqCcdD5A=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2/go.mod h1:QyVsSSN64v5TGltphKLQ2sQxe4OBQg0J1eKRcVBnfgE=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.11.0 h1:MhRfI58HblXzCtWEZCO0feHs8LweePB3s90r7WaR1KU=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.11.0/go.mod h1:okZ+ZURbArNdlJ+ptXoyHNuOETzOl1Oww19rm8I2WLA=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0 h1:PiSrjRPpkQNjrM8H0WwKMnZUdu1RGMtd/LdGKUrOo+c=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0/go.mod h1:oDrbWx4ewMylP7xHivfgixbfGBT6APAwsSoHRKotnIc=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0 h1:mlmW46Q0B79I+Aj4azKC6xDMFN9a9SyZWESlGWYXbFs=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0/go.mod h1:PXe2h+LKcWTX9afWdZoHyODqR4fBa5boUM/8uJfZ0Jo=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5gYVyhkij+RTJ/VR6QIUaCfWeaFm2ycsjQ=
github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs=
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/Graylog2/go-gelf v0.0.0-20191017102106-1550ee647df0 h1:cOjLyhBhe91glgZZNbQUg9BJC57l6BiSKov0Ivv7k0U=
@@ -46,6 +46,8 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.14.0-rc.1 h1:qAPXKwGOkVn8LlqgBN8GS0bxZ83hOJpcjxzmlQKxKsQ=
github.com/Microsoft/hcsshim v0.14.0-rc.1/go.mod h1:hTKFGbnDtQb1wHiOWv4v0eN+7boSWAHyK/tNAaYZL0c=
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
github.com/RackSec/srslog v0.0.0-20180709174129-a4725f04ec91 h1:vX+gnvBc56EbWYrmlhYbFYRaeikAke1GL84N4BEYOFE=
github.com/RackSec/srslog v0.0.0-20180709174129-a4725f04ec91/go.mod h1:cDLGBht23g0XQdLjzn6xOGXDkLK182YfINAaZEQLCHQ=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
@@ -100,6 +102,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
@@ -116,6 +119,8 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/cfssl v1.6.4 h1:NMOvfrEjFfC63K3SGXgAnFdsgkmiq4kATme5BfcqrO8=
github.com/cloudflare/cfssl v1.6.4/go.mod h1:8b3CQMxfWPAeom3zBnGJ6sd+G1NkL5TXqmDXacb+1J0=
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv1aFbZMiM9vblcSArJRf2Irls=
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
@@ -149,14 +154,14 @@ github.com/containerd/go-runc v1.1.0 h1:OX4f+/i2y5sUT7LhmcJH7GYrjjhHa1QI4e8yO0gG
github.com/containerd/go-runc v1.1.0/go.mod h1:xJv2hFF7GvHtTJd9JqTS2UVxMkULUYw4JN5XAUZqH5U=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/nydus-snapshotter v0.15.2 h1:qsHI4M+Wwrf6Jr4eBqhNx8qh+YU0dSiJ+WPmcLFWNcg=
github.com/containerd/nydus-snapshotter v0.15.2/go.mod h1:FfwH2KBkNYoisK/e+KsmNr7xTU53DmnavQHMFOcXwfM=
github.com/containerd/nydus-snapshotter v0.15.4 h1:l59kGRVMtwMLDLh322HsWhEsBCkRKMkGWYV5vBeLYCE=
github.com/containerd/nydus-snapshotter v0.15.4/go.mod h1:eRJqnxQDr48HNop15kZdLZpFF5B6vf6Q11Aq1K0E4Ms=
github.com/containerd/platforms v1.0.0-rc.2 h1:0SPgaNZPVWGEi4grZdV8VRYQn78y+nm6acgLGv/QzE4=
github.com/containerd/platforms v1.0.0-rc.2/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y=
github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8=
github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8=
github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU=
github.com/containerd/stargz-snapshotter/estargz v0.17.0 h1:+TyQIsR/zSFI1Rm31EQBwpAA1ovYgIKHy7kctL3sLcE=
github.com/containerd/stargz-snapshotter/estargz v0.17.0/go.mod h1:s06tWAiJcXQo9/8AReBCIo/QxcXFZ2n4qfsRnpl71SM=
github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ=
github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
@@ -186,8 +191,8 @@ github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v28.4.0+incompatible h1:RBcf3Kjw2pMtwui5V0DIMdyeab8glEw5QY0UUU4C9kY=
github.com/docker/cli v28.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v28.5.0+incompatible h1:crVqLrtKsrhC9c00ythRx435H8LiQnUKRtJLRR+Auxk=
github.com/docker/cli v28.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
@@ -242,13 +247,13 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=
github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f h1:16RtHeWGkJMc80Etb8RPCcKevXGldr57+LOyZt8zOlg=
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f/go.mod h1:ijRvpgDJDI262hYq/IQVYgf8hd8IHUs93Ol0kvMBAx4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -273,8 +278,8 @@ github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8l
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/certificate-transparency-go v1.1.4 h1:hCyXHDbtqlr/lMXU0D4WgbalXL0Zk4dSWWMbPV8VrqY=
github.com/google/certificate-transparency-go v1.1.4/go.mod h1:D6lvbfwckhNrbM9WVl1EVeMOyzC19mpIjMOI4nxBHtQ=
github.com/google/certificate-transparency-go v1.3.2 h1:9ahSNZF2o7SYMaKaXhAumVEzXB2QaayzII9C8rv7v+A=
github.com/google/certificate-transparency-go v1.3.2/go.mod h1:H5FpMUaGa5Ab2+KCYsxg6sELw3Flkl7pGZzWdBoYLXs=
github.com/google/go-cmp v0.1.1-0.20171103154506-982329095285/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -289,19 +294,19 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY=
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U=
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o=
github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk=
github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo=
github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gregjones/httpcache v0.0.0-20170920190843-316c5e0ff04e/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
@@ -349,6 +354,8 @@ github.com/hashicorp/memberlist v0.4.0 h1:k3uda5gZcltmafuFF+UFqNEl5PrH+yPZ4zkjp1
github.com/hashicorp/memberlist v0.4.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0=
github.com/hashicorp/serf v0.8.5 h1:ZynDUIQiA8usmRgPdGPHFdPnb1wgGI9tK3mO9hcAJjc=
github.com/hashicorp/serf v0.8.5/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc1oal+k=
github.com/hiddeco/sshsig v0.2.0 h1:gMWllgKCITXdydVkDL+Zro0PU96QI55LwUwebSwNTSw=
github.com/hiddeco/sshsig v0.2.0/go.mod h1:nJc98aGgiH6Yql2doqH4CTBVHexQA40Q+hMMLHP4EqE=
github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU=
github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo=
github.com/inconshreveable/log15 v0.0.0-20170622235902-74a0988b5f80/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
@@ -410,8 +417,8 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F
github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/buildkit v0.25.2 h1:mReLKDPv05cqk6o/u3ixq2/iTsWGHoUO5Zg3lojrQTk=
github.com/moby/buildkit v0.25.2/go.mod h1:phM8sdqnvgK2y1dPDnbwI6veUCXHOZ6KFSl6E164tkc=
github.com/moby/buildkit v0.26.0-rc2 h1:HLS1HtBlxdaz8NjHI5YAaN4c8NOPtUrIJ5jIq/b6tpI=
github.com/moby/buildkit v0.26.0-rc2/go.mod h1:ylDa7IqzVJgLdi/wO7H1qLREFQpmhFbw2fbn4yoTw40=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
@@ -426,6 +433,8 @@ github.com/moby/moby/client v0.1.0 h1:nt+hn6O9cyJQqq5UWnFGqsZRTS/JirUqzPjEl0Bdc/
github.com/moby/moby/client v0.1.0/go.mod h1:O+/tw5d4a1Ha/ZA/tPxIZJapJRUS6LNZ1wiVRxYHyUE=
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/policy-helpers v0.0.0-20251105011237-bcaa71c99f14 h1:JO22uXMy3CN7wh7A/wrtYQWV1WYQMg2gh6d8YO325k4=
github.com/moby/policy-helpers v0.0.0-20251105011237-bcaa71c99f14/go.mod h1:HJfK0E8dR+Jpk5anJ3oADg2dRSom1gJK17sqEiiMS7w=
github.com/moby/profiles/apparmor v0.1.0 h1:dMUt6fqdOeU9tfKjntPN9hBY1C5tJtsUWZNiIuHK8QM=
github.com/moby/profiles/apparmor v0.1.0/go.mod h1:2iRxPw+MrPuDvmb5lAEAeLB1kcOt7AzZeW3paBs2TQY=
github.com/moby/profiles/seccomp v0.1.0 h1:kVf1lc5ytNB1XPxEdZUVF+oPpbBYJHR50eEvPt/9k8A=
@@ -551,8 +560,8 @@ github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb
github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/secure-systems-lab/go-securesystemslib v0.6.0 h1:T65atpAVCJQK14UA57LMdZGpHi4QYSH/9FZyNGqMYIA=
github.com/secure-systems-lab/go-securesystemslib v0.6.0/go.mod h1:8Mtpo9JKks/qhPG4HGZ2LGMvrPbzuxwfz/f/zLfEWkk=
github.com/secure-systems-lab/go-securesystemslib v0.9.1 h1:nZZaNz4DiERIQguNy0cL5qTdn9lR8XKHf4RUyG1Sx3g=
github.com/secure-systems-lab/go-securesystemslib v0.9.1/go.mod h1:np53YzT0zXGMv6x4iEWc9Z59uR+x+ndLwCLqPYpLXVU=
github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=
github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@@ -702,8 +711,8 @@ golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU=
golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
@@ -795,8 +804,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/api v0.0.0-20170921000349-586095a6e407/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.214.0 h1:h2Gkq07OYi6kusGOaT/9rnNljuXmqPnaig7WGPmKbwA=
google.golang.org/api v0.214.0/go.mod h1:bYPpLG8AyeMWwDU6NXoB00xC0DFkikVvd5MfwoxjLqE=
google.golang.org/api v0.248.0 h1:hUotakSkcwGdYUqzCRc5yGYsg4wXxpkKlW5ryVqvC1Y=
google.golang.org/api v0.248.0/go.mod h1:yAFUAF56Li7IuIQbTFoLwXTCI6XCFKueOlS7S9e4F9k=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
@@ -804,8 +813,8 @@ google.golang.org/genproto v0.0.0-20170918111702-1e559d0a00ee/go.mod h1:JiN7NxoA
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk=
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc=
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
@@ -850,8 +859,6 @@ gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM=
kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY=

View File

@@ -1,16 +1,18 @@
{
"auth": "0.13.0",
"auth/oauth2adapt": "0.2.6",
"bigquery": "1.65.0",
"bigtable": "1.33.0",
"auth": "0.16.4",
"auth/oauth2adapt": "0.2.8",
"bigquery": "1.69.0",
"bigquery/v2": "0.0.0",
"bigtable": "1.38.0",
"datastore": "1.20.0",
"errorreporting": "0.3.2",
"firestore": "1.17.0",
"logging": "1.12.0",
"profiler": "0.4.2",
"pubsub": "1.45.3",
"firestore": "1.18.0",
"logging": "1.13.0",
"profiler": "0.4.3",
"pubsub": "1.50.0",
"pubsub/v2": "2.0.0",
"pubsublite": "1.8.2",
"spanner": "1.73.0",
"storage": "1.48.0",
"vertexai": "0.13.2"
"spanner": "1.84.1",
"storage": "1.56.0",
"vertexai": "0.15.0"
}

View File

@@ -1,153 +1,164 @@
{
"accessapproval": "1.8.2",
"accesscontextmanager": "1.9.2",
"advisorynotifications": "1.5.2",
"ai": "0.9.0",
"aiplatform": "1.69.0",
"alloydb": "1.14.0",
"analytics": "0.25.2",
"apigateway": "1.7.2",
"apigeeconnect": "1.7.2",
"apigeeregistry": "0.9.2",
"apihub": "0.1.2",
"apikeys": "1.2.2",
"appengine": "1.9.2",
"apphub": "0.2.2",
"apps": "0.5.2",
"area120": "0.9.2",
"artifactregistry": "1.16.0",
"asset": "1.20.3",
"assuredworkloads": "1.12.2",
"automl": "1.14.3",
"backupdr": "1.2.1",
"baremetalsolution": "1.3.2",
"batch": "1.11.4",
"beyondcorp": "1.1.2",
"billing": "1.20.0",
"binaryauthorization": "1.9.2",
"certificatemanager": "1.9.2",
"channel": "1.19.1",
"chat": "0.9.0",
"cloudbuild": "1.19.1",
"cloudcontrolspartner": "1.2.1",
"clouddms": "1.8.2",
"cloudprofiler": "0.4.2",
"cloudquotas": "1.2.0",
"cloudtasks": "1.13.2",
"commerce": "1.2.1",
"compute": "1.31.0",
"compute/metadata": "0.6.0",
"confidentialcomputing": "1.8.0",
"config": "1.2.0",
"contactcenterinsights": "1.16.0",
"container": "1.42.0",
"containeranalysis": "0.13.2",
"datacatalog": "1.24.0",
"dataflow": "0.10.2",
"dataform": "0.10.2",
"datafusion": "1.8.2",
"datalabeling": "0.9.2",
"dataplex": "1.20.0",
"dataproc": "2.10.0",
"dataqna": "0.9.2",
"datastream": "1.12.0",
"deploy": "1.26.0",
"developerconnect": "0.3.0",
"dialogflow": "1.63.0",
"discoveryengine": "1.16.0",
"dlp": "1.20.0",
"documentai": "1.35.0",
"domains": "0.10.2",
"edgecontainer": "1.4.0",
"edgenetwork": "1.2.2",
"essentialcontacts": "1.7.2",
"eventarc": "1.15.0",
"filestore": "1.9.2",
"functions": "1.19.2",
"gkebackup": "1.6.2",
"gkeconnect": "0.12.0",
"gkehub": "0.15.2",
"gkemulticloud": "1.4.1",
"grafeas": "0.3.12",
"gsuiteaddons": "1.7.2",
"iam": "1.3.0",
"iap": "1.10.2",
"identitytoolkit": "0.2.2",
"ids": "1.5.2",
"iot": "1.8.2",
"kms": "1.20.2",
"language": "1.14.2",
"lifesciences": "0.10.2",
"longrunning": "0.6.3",
"managedidentities": "1.7.2",
"managedkafka": "0.3.0",
"maps": "1.17.0",
"mediatranslation": "0.9.2",
"memcache": "1.11.2",
"metastore": "1.14.2",
"migrationcenter": "1.1.2",
"monitoring": "1.22.0",
"netapp": "1.5.0",
"networkconnectivity": "1.16.0",
"networkmanagement": "1.17.0",
"networksecurity": "0.10.2",
"networkservices": "0.2.2",
"notebooks": "1.12.2",
"optimization": "1.7.2",
"oracledatabase": "0.1.2",
"orchestration": "1.11.2",
"orgpolicy": "1.14.1",
"osconfig": "1.14.2",
"oslogin": "1.14.2",
"parallelstore": "0.9.0",
"phishingprotection": "0.9.2",
"policysimulator": "0.3.2",
"policytroubleshooter": "1.11.2",
"privatecatalog": "0.10.2",
"privilegedaccessmanager": "0.2.2",
"rapidmigrationassessment": "1.1.2",
"recaptchaenterprise": "2.19.1",
"recommendationengine": "0.9.2",
"recommender": "1.13.2",
"redis": "1.17.2",
"resourcemanager": "1.10.2",
"resourcesettings": "1.8.2",
"retail": "1.19.1",
"run": "1.8.0",
"scheduler": "1.11.2",
"secretmanager": "1.14.2",
"securesourcemanager": "1.3.0",
"security": "1.18.2",
"securitycenter": "1.35.2",
"securitycentermanagement": "1.1.2",
"securityposture": "0.2.2",
"servicecontrol": "1.14.2",
"servicedirectory": "1.12.2",
"servicehealth": "1.2.0",
"servicemanagement": "1.10.2",
"serviceusage": "1.9.2",
"shell": "1.8.2",
"shopping": "0.13.0",
"speech": "1.25.2",
"storageinsights": "1.1.2",
"storagetransfer": "1.11.2",
"streetview": "0.2.2",
"support": "1.1.2",
"talent": "1.7.2",
"telcoautomation": "1.1.2",
"texttospeech": "1.10.0",
"tpu": "1.7.2",
"trace": "1.11.2",
"translate": "1.12.2",
"video": "1.23.2",
"videointelligence": "1.12.2",
"vision": "2.9.2",
"visionai": "0.4.2",
"vmmigration": "1.8.2",
"vmwareengine": "1.3.2",
"vpcaccess": "1.8.2",
"webrisk": "1.10.2",
"websecurityscanner": "1.7.2",
"workflows": "1.13.2",
"workstations": "1.1.2"
"accessapproval": "1.8.7",
"accesscontextmanager": "1.9.6",
"advisorynotifications": "1.5.6",
"ai": "0.12.1",
"aiplatform": "1.98.0",
"alloydb": "1.18.0",
"analytics": "0.29.0",
"apigateway": "1.7.7",
"apigeeconnect": "1.7.7",
"apigeeregistry": "0.9.6",
"apihub": "0.1.5",
"apikeys": "1.2.7",
"appengine": "1.9.7",
"apphub": "0.3.1",
"apps": "0.8.0",
"area120": "0.9.7",
"artifactregistry": "1.17.1",
"asset": "1.21.1",
"assuredworkloads": "1.12.6",
"automl": "1.14.7",
"backupdr": "1.4.0",
"baremetalsolution": "1.3.6",
"batch": "1.12.2",
"beyondcorp": "1.1.6",
"billing": "1.20.4",
"binaryauthorization": "1.9.5",
"certificatemanager": "1.9.5",
"channel": "1.20.0",
"chat": "0.15.0",
"chronicle": "0.1.1",
"cloudbuild": "1.22.3",
"cloudcontrolspartner": "1.4.0",
"clouddms": "1.8.7",
"cloudprofiler": "0.4.5",
"cloudquotas": "1.4.0",
"cloudtasks": "1.13.6",
"commerce": "1.2.5",
"compute": "1.43.0",
"compute/metadata": "0.8.0",
"confidentialcomputing": "1.9.2",
"config": "1.4.0",
"configdelivery": "0.1.0",
"contactcenterinsights": "1.17.3",
"container": "1.44.0",
"containeranalysis": "0.14.1",
"datacatalog": "1.26.0",
"dataflow": "0.11.0",
"dataform": "0.12.0",
"datafusion": "1.8.6",
"datalabeling": "0.9.6",
"dataplex": "1.26.0",
"dataproc": "2.14.0",
"dataqna": "0.9.7",
"datastream": "1.15.0",
"deploy": "1.27.2",
"developerconnect": "0.4.0",
"devicestreaming": "0.1.0",
"dialogflow": "1.69.0",
"discoveryengine": "1.20.0",
"dlp": "1.24.0",
"documentai": "1.37.0",
"domains": "0.10.6",
"edgecontainer": "1.4.3",
"edgenetwork": "1.2.6",
"essentialcontacts": "1.7.6",
"eventarc": "1.15.5",
"filestore": "1.10.2",
"financialservices": "0.1.3",
"functions": "1.19.6",
"gkebackup": "1.8.0",
"gkeconnect": "0.12.4",
"gkehub": "0.15.6",
"gkemulticloud": "1.5.3",
"grafeas": "0.3.16",
"gsuiteaddons": "1.7.7",
"iam": "1.5.2",
"iap": "1.11.2",
"identitytoolkit": "0.2.5",
"ids": "1.5.6",
"iot": "1.8.6",
"kms": "1.22.0",
"language": "1.14.5",
"licensemanager": "0.1.0",
"lifesciences": "0.10.6",
"longrunning": "0.6.7",
"lustre": "0.2.0",
"maintenance": "0.1.1",
"managedidentities": "1.7.6",
"managedkafka": "0.7.0",
"maps": "1.22.0",
"mediatranslation": "0.9.6",
"memcache": "1.11.6",
"memorystore": "0.3.0",
"metastore": "1.14.7",
"migrationcenter": "1.1.5",
"modelarmor": "0.6.0",
"monitoring": "1.24.2",
"netapp": "1.9.0",
"networkconnectivity": "1.18.0",
"networkmanagement": "1.20.0",
"networksecurity": "0.10.6",
"networkservices": "0.5.0",
"notebooks": "1.12.6",
"optimization": "1.7.6",
"oracledatabase": "0.5.0",
"orchestration": "1.11.9",
"orgpolicy": "1.15.0",
"osconfig": "1.15.0",
"oslogin": "1.14.6",
"parallelstore": "0.11.3",
"parametermanager": "0.3.0",
"phishingprotection": "0.9.6",
"policysimulator": "0.4.0",
"policytroubleshooter": "1.11.6",
"privatecatalog": "0.10.7",
"privilegedaccessmanager": "0.3.0",
"rapidmigrationassessment": "1.1.7",
"recaptchaenterprise": "2.20.4",
"recommendationengine": "0.9.6",
"recommender": "1.13.5",
"redis": "1.18.2",
"resourcemanager": "1.10.6",
"retail": "1.24.0",
"run": "1.12.0",
"scheduler": "1.11.7",
"secretmanager": "1.15.0",
"securesourcemanager": "1.4.0",
"security": "1.19.0",
"securitycenter": "1.37.0",
"securitycentermanagement": "1.1.5",
"securityposture": "0.2.5",
"servicecontrol": "1.14.5",
"servicedirectory": "1.12.6",
"servicehealth": "1.2.3",
"servicemanagement": "1.10.6",
"serviceusage": "1.9.6",
"shell": "1.8.6",
"shopping": "0.25.0",
"spanner/benchmarks": "0.1.0",
"speech": "1.28.0",
"storagebatchoperations": "0.1.0",
"storageinsights": "1.2.0",
"storagetransfer": "1.13.0",
"streetview": "0.2.5",
"support": "1.4.0",
"talent": "1.8.3",
"telcoautomation": "1.1.5",
"texttospeech": "1.13.0",
"tpu": "1.8.3",
"trace": "1.11.6",
"translate": "1.12.6",
"video": "1.25.0",
"videointelligence": "1.12.6",
"vision": "2.9.5",
"visionai": "0.4.5",
"vmmigration": "1.8.6",
"vmwareengine": "1.3.5",
"vpcaccess": "1.8.6",
"webrisk": "1.11.1",
"websecurityscanner": "1.7.6",
"workflows": "1.14.2",
"workstations": "1.1.5"
}

View File

@@ -1,3 +1,3 @@
{
".": "0.117.0"
".": "0.121.6"
}

108
vendor/cloud.google.com/go/CHANGES.md generated vendored
View File

@@ -1,5 +1,113 @@
# Changes
## [0.121.6](https://github.com/googleapis/google-cloud-go/compare/v0.121.5...v0.121.6) (2025-08-14)
### Bug Fixes
* **internal/librariangen:** Fix Dockerfile permissions for go mod tidy ([#12704](https://github.com/googleapis/google-cloud-go/issues/12704)) ([0e70a0b](https://github.com/googleapis/google-cloud-go/commit/0e70a0b6afccc016c67337f340e2755fe7a476ca))
## [0.121.5](https://github.com/googleapis/google-cloud-go/compare/v0.121.4...v0.121.5) (2025-08-12)
### Bug Fixes
* **internal/librariangen:** Get README title from service config yaml ([#12676](https://github.com/googleapis/google-cloud-go/issues/12676)) ([b3b8f70](https://github.com/googleapis/google-cloud-go/commit/b3b8f70a15ae477885f3ecc92e01ae37b7505de3))
* **internal/librariangen:** Update source_paths to source_roots in generate-request.json ([#12691](https://github.com/googleapis/google-cloud-go/issues/12691)) ([2adb6f9](https://github.com/googleapis/google-cloud-go/commit/2adb6f9a67f21fba32371fb4b3dcfb7204309560))
## [0.121.4](https://github.com/googleapis/google-cloud-go/compare/v0.121.3...v0.121.4) (2025-07-17)
### Bug Fixes
* **geminidataanalytics:** Correct resource reference type for `parent` field in `data_chat_service.proto` ([98ba6f0](https://github.com/googleapis/google-cloud-go/commit/98ba6f06e69685bca510ca85c12124434f9ba1e8))
* **internal/postprocessor:** Add git ([#12524](https://github.com/googleapis/google-cloud-go/issues/12524)) ([82030ee](https://github.com/googleapis/google-cloud-go/commit/82030eec5d66f25ebc3fee1fda4b45ced370fc2b))
## [0.121.3](https://github.com/googleapis/google-cloud-go/compare/v0.121.2...v0.121.3) (2025-06-25)
### Documentation
* **impersonate:** Address TODO in impersonate/example_test.go ([#12401](https://github.com/googleapis/google-cloud-go/issues/12401)) ([dd096ec](https://github.com/googleapis/google-cloud-go/commit/dd096ec81944e785b9245fda7e7b46e9908cfe8f))
## [0.121.2](https://github.com/googleapis/google-cloud-go/compare/v0.121.1...v0.121.2) (2025-05-21)
### Documentation
* **internal/generated:** Remove outdated pubsub snippets ([#12284](https://github.com/googleapis/google-cloud-go/issues/12284)) ([0338a40](https://github.com/googleapis/google-cloud-go/commit/0338a40d70206317d319e69911be0321fbb54e3f))
## [0.121.1](https://github.com/googleapis/google-cloud-go/compare/v0.121.0...v0.121.1) (2025-05-13)
### Bug Fixes
* **civil:** Add support for civil.Date, civil.Time and civil.DateTime arguments to their respective Scan methods ([#12240](https://github.com/googleapis/google-cloud-go/issues/12240)) ([7127ce9](https://github.com/googleapis/google-cloud-go/commit/7127ce9992f890667f2c8f75c924136b0e94f115)), refs [#12060](https://github.com/googleapis/google-cloud-go/issues/12060)
## [0.121.0](https://github.com/googleapis/google-cloud-go/compare/v0.120.1...v0.121.0) (2025-04-28)
### Features
* **debugger:** Remove debugger/apiv2 client ([#12050](https://github.com/googleapis/google-cloud-go/issues/12050)) ([af8641e](https://github.com/googleapis/google-cloud-go/commit/af8641e7d011349afa774b668b30a95b007fd076))
## [0.120.1](https://github.com/googleapis/google-cloud-go/compare/v0.120.0...v0.120.1) (2025-04-14)
### Bug Fixes
* **readme:** Update authentication section ([#11918](https://github.com/googleapis/google-cloud-go/issues/11918)) ([2fda860](https://github.com/googleapis/google-cloud-go/commit/2fda86031820ad7d29322f03ad6f34871ad5ff59))
## [0.120.0](https://github.com/googleapis/google-cloud-go/compare/v0.119.0...v0.120.0) (2025-03-20)
### Features
* **civil:** Implement database/sql.Scanner|Valuer ([#1145](https://github.com/googleapis/google-cloud-go/issues/1145)) ([#11808](https://github.com/googleapis/google-cloud-go/issues/11808)) ([cbe4419](https://github.com/googleapis/google-cloud-go/commit/cbe4419c17f677c05f3f52c2080861adce705db4))
### Bug Fixes
* **third_party/pkgsite:** Increase comment size limit ([#11877](https://github.com/googleapis/google-cloud-go/issues/11877)) ([587b5cc](https://github.com/googleapis/google-cloud-go/commit/587b5ccc684ad99cb9eeba897304b7143564d423))
## [0.119.0](https://github.com/googleapis/google-cloud-go/compare/v0.118.3...v0.119.0) (2025-03-11)
### Features
* **main:** Add support for listening on custom host to internal/testutil ([#11780](https://github.com/googleapis/google-cloud-go/issues/11780)) ([9608a09](https://github.com/googleapis/google-cloud-go/commit/9608a09a5d41778c7bb93792b5d5128d7081d4a6)), refs [#11586](https://github.com/googleapis/google-cloud-go/issues/11586)
## [0.118.3](https://github.com/googleapis/google-cloud-go/compare/v0.118.2...v0.118.3) (2025-02-20)
### Bug Fixes
* **main:** Bump github.com/envoyproxy/go-control-plane/envoy to v1.32.4 ([#11591](https://github.com/googleapis/google-cloud-go/issues/11591)) ([d52451a](https://github.com/googleapis/google-cloud-go/commit/d52451aa22fb7120e37b43161d3d3103c19e5943))
## [0.118.2](https://github.com/googleapis/google-cloud-go/compare/v0.118.1...v0.118.2) (2025-02-06)
### Bug Fixes
* **internal/godocfx:** Don't save timestamps until modules are successfully processed ([#11563](https://github.com/googleapis/google-cloud-go/issues/11563)) ([8f38b3d](https://github.com/googleapis/google-cloud-go/commit/8f38b3d912354027c30977b5adc928e0c6eff7a9))
* **internal/godocfx:** Retry go get with explicit envoy dependency ([#11564](https://github.com/googleapis/google-cloud-go/issues/11564)) ([a06a6a5](https://github.com/googleapis/google-cloud-go/commit/a06a6a5542939b6239e1ec2c944eb1aae56745d9))
## [0.118.1](https://github.com/googleapis/google-cloud-go/compare/v0.118.0...v0.118.1) (2025-01-30)
### Bug Fixes
* **main:** Remove OpenCensus dependency ([6243d91](https://github.com/googleapis/google-cloud-go/commit/6243d910b2bb502211d8308f9cc7723829d9f844))
## [0.118.0](https://github.com/googleapis/google-cloud-go/compare/v0.117.0...v0.118.0) (2025-01-02)
### Features
* **civil:** Add AddMonths, AddYears and Weekday methods to Date ([#11340](https://github.com/googleapis/google-cloud-go/issues/11340)) ([d45f1a0](https://github.com/googleapis/google-cloud-go/commit/d45f1a01ebff868418aa14fe762ef7d1334f797d))
## [0.117.0](https://github.com/googleapis/google-cloud-go/compare/v0.116.0...v0.117.0) (2024-12-16)

View File

@@ -138,23 +138,38 @@ Finally, in the general project, create an API key for the translate API:
#### Local Setup
Once the three projects are created and configured, set the following environment
variables:
Once the three projects are created and configured, set the following
environment variables:
- `GCLOUD_TESTS_GOLANG_PROJECT_ID`: Developers Console project's ID (e.g.
bamboo-shift-455) for the general project.
- `GCLOUD_TESTS_GOLANG_KEY`: The path to the JSON key file of the general
project's service account.
- `GCLOUD_TESTS_GOLANG_DATASTORE_DATABASES`: Comma separated list of developer's Datastore databases. If not provided, default database i.e. empty string is used.
- `GCLOUD_TESTS_GOLANG_DATASTORE_DATABASES`: Comma separated list of developer's
Datastore databases. If not provided, default database i.e. empty string is used.
- `GCLOUD_TESTS_GOLANG_FIRESTORE_PROJECT_ID`: Developers Console project's ID
(e.g. doorway-cliff-677) for the Firestore project.
- `GCLOUD_TESTS_GOLANG_FIRESTORE_DATABASES` : Comma separated list of developer's Firestore databases. If not provided, default database is used.
- `GCLOUD_TESTS_GOLANG_FIRESTORE_DATABASES`: Comma separated list of developer's
Firestore databases. If not provided, default database is used.
- `GCLOUD_TESTS_GOLANG_FIRESTORE_KEY`: The path to the JSON key file of the
Firestore project's service account.
- `GCLOUD_TESTS_API_KEY`: API key for using the Translate API created above.
- `GCLOUD_TESTS_GOLANG_SECONDARY_BIGTABLE_PROJECT_ID`: Developers Console project's ID (e.g. doorway-cliff-677) for Bigtable optional secondary project. This can be same as Firestore project or any project other than the general project.
- `GCLOUD_TESTS_BIGTABLE_CLUSTER`: Cluster ID of Bigtable cluster in general project
- `GCLOUD_TESTS_BIGTABLE_PRI_PROJ_SEC_CLUSTER`: Optional. Cluster ID of Bigtable secondary cluster in general project
- `GCLOUD_TESTS_GOLANG_SECONDARY_BIGTABLE_PROJECT_ID`: Developers Console
project's ID (e.g. doorway-cliff-677) for Bigtable optional secondary project.
This can be same as Firestore project or any project other than the general
project.
- `GCLOUD_TESTS_BIGTABLE_CLUSTER`: Cluster ID of Bigtable cluster in general
project.
- `GCLOUD_TESTS_BIGTABLE_PRI_PROJ_SEC_CLUSTER`: Optional. Cluster ID of Bigtable
secondary cluster in general project
- `TEST_UNIVERSE_DOMAIN`: Optional. Universe domain to test universe domain
functionality against.
- `TEST_UNIVERSE_PROJECT_ID`: Optional. Project ID within the universe domain
for testing.
- `TEST_UNIVERSE_LOCATION`: Optional. Available location within the universe
domain.
- `TEST_UNIVERSE_DOMAIN_CREDENTIAL`: Optional. The path to the JSON key file of
the universe domain's service account.
As part of the setup that follows, the following variables will be configured:

44
vendor/cloud.google.com/go/README.md generated vendored
View File

@@ -20,30 +20,39 @@ For an updated list of all of our released APIs please see our
## [Go Versions Supported](#supported-versions)
**Note:** As of Jan 1, 2025 the Cloud Client Libraries for Go will support the
two most-recent major Go releases -- the same [policy](https://go.dev/doc/devel/release#policy)
the Go programming language follows.
Our libraries are compatible with at least the three most recent, major Go
releases. They are currently compatible with:
Our libraries are compatible with the two most recent major Go
releases, the same [policy](https://go.dev/doc/devel/release#policy) the Go
programming language follows. This means the currently supported versions are:
- Go 1.23
- Go 1.22
- Go 1.21
- Go 1.24
## Authorization
## Authentication
By default, each API will use [Google Application Default Credentials](https://developers.google.com/identity/protocols/application-default-credentials)
for authorization credentials used in calling the API endpoints. This will allow your
application to run in many environments without requiring explicit configuration.
By default, each client library will use [Application Default Credentials](https://developers.google.com/identity/protocols/application-default-credentials)
(ADC) to automatically configure the credentials used in calling the API endpoint.
When using the libraries in a Google Cloud Platform environment such as Compute
Engine, Kubernetes Engine, or App Engine, no additional authentication steps are
necessary. See [Authentication methods at Google](https://cloud.google.com/docs/authentication)
and [Authenticate for using client libraries](https://cloud.google.com/docs/authentication/client-libraries)
for more information.
```go
client, err := storage.NewClient(ctx)
```
To authorize using a
[JSON key file](https://cloud.google.com/iam/docs/managing-service-account-keys),
pass
For applications running elsewhere, such as your local development environment,
you can use the `gcloud auth application-default login` command from the
[Google Cloud CLI](https://cloud.google.com/cli) to set user credentials in
your local filesystem. Application Default Credentials will automatically detect
these credentials. See [Set up ADC for a local development
environment](https://cloud.google.com/docs/authentication/set-up-adc-local-dev-environment)
for more information.
Alternately, you may need to provide an explicit path to your credentials. To authenticate
using a [service account](https://cloud.google.com/docs/authentication#service-accounts)
key file, either set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to the path
to your key file, or programmatically pass
[`option.WithCredentialsFile`](https://pkg.go.dev/google.golang.org/api/option#WithCredentialsFile)
to the `NewClient` function of the desired package. For example:
@@ -51,14 +60,15 @@ to the `NewClient` function of the desired package. For example:
client, err := storage.NewClient(ctx, option.WithCredentialsFile("path/to/keyfile.json"))
```
You can exert more control over authorization by using the
You can exert even more control over authentication by using the
[credentials](https://pkg.go.dev/cloud.google.com/go/auth/credentials) package to
create an [auth.Credentials](https://pkg.go.dev/cloud.google.com/go/auth#Credentials).
Then pass [`option.WithAuthCredentials`](https://pkg.go.dev/google.golang.org/api/option#WithAuthCredentials)
to the `NewClient` function:
```go
creds := ...
creds, err := credentials.DetectDefault(&credentials.DetectOptions{...})
...
client, err := storage.NewClient(ctx, option.WithAuthCredentials(creds))
```

View File

@@ -1,5 +1,84 @@
# Changelog
## [0.16.5](https://github.com/googleapis/google-cloud-go/compare/auth/v0.16.4...auth/v0.16.5) (2025-08-14)
### Bug Fixes
* **auth:** Improve error message for unknown credentials type ([#12673](https://github.com/googleapis/google-cloud-go/issues/12673)) ([558b164](https://github.com/googleapis/google-cloud-go/commit/558b16429f621276694405fa5f2091199f2d4c4d))
* **auth:** Set Content-Type in userTokenProvider.exchangeToken ([#12634](https://github.com/googleapis/google-cloud-go/issues/12634)) ([1197ebc](https://github.com/googleapis/google-cloud-go/commit/1197ebcbca491f8c610da732c7361c90bc6f46d0))
## [0.16.4](https://github.com/googleapis/google-cloud-go/compare/auth/v0.16.3...auth/v0.16.4) (2025-08-06)
### Bug Fixes
* **auth:** Add UseDefaultClient: true to metadata.Options ([#12666](https://github.com/googleapis/google-cloud-go/issues/12666)) ([1482191](https://github.com/googleapis/google-cloud-go/commit/1482191e88236693efef68769752638281566766)), refs [#11078](https://github.com/googleapis/google-cloud-go/issues/11078) [#12657](https://github.com/googleapis/google-cloud-go/issues/12657)
## [0.16.3](https://github.com/googleapis/google-cloud-go/compare/auth/v0.16.2...auth/v0.16.3) (2025-07-17)
### Bug Fixes
* **auth:** Fix race condition in cachedTokenProvider.tokenAsync ([#12586](https://github.com/googleapis/google-cloud-go/issues/12586)) ([73867cc](https://github.com/googleapis/google-cloud-go/commit/73867ccc1e9808d65361bcfc0776bd95fe34dbb3))
## [0.16.2](https://github.com/googleapis/google-cloud-go/compare/auth/v0.16.1...auth/v0.16.2) (2025-06-04)
### Bug Fixes
* **auth:** Add back DirectPath misconfiguration logging ([#11162](https://github.com/googleapis/google-cloud-go/issues/11162)) ([8d52da5](https://github.com/googleapis/google-cloud-go/commit/8d52da58da5a0ed77a0f6307d1b561bc045406a1))
* **auth:** Remove s2a fallback option ([#12354](https://github.com/googleapis/google-cloud-go/issues/12354)) ([d5acc59](https://github.com/googleapis/google-cloud-go/commit/d5acc599cd775ddc404349e75906fa02e8ff133e))
## [0.16.1](https://github.com/googleapis/google-cloud-go/compare/auth/v0.16.0...auth/v0.16.1) (2025-04-23)
### Bug Fixes
* **auth:** Clone detectopts before assigning TokenBindingType ([#11881](https://github.com/googleapis/google-cloud-go/issues/11881)) ([2167b02](https://github.com/googleapis/google-cloud-go/commit/2167b020fdc43b517c2b6ecca264a10e357ea035))
## [0.16.0](https://github.com/googleapis/google-cloud-go/compare/auth/v0.15.0...auth/v0.16.0) (2025-04-14)
### Features
* **auth/credentials:** Return X.509 certificate chain as subject token ([#11948](https://github.com/googleapis/google-cloud-go/issues/11948)) ([d445a3f](https://github.com/googleapis/google-cloud-go/commit/d445a3f66272ffd5c39c4939af9bebad4582631c)), refs [#11757](https://github.com/googleapis/google-cloud-go/issues/11757)
* **auth:** Configure DirectPath bound credentials from AllowedHardBoundTokens ([#11665](https://github.com/googleapis/google-cloud-go/issues/11665)) ([0fc40bc](https://github.com/googleapis/google-cloud-go/commit/0fc40bcf4e4673704df0973e9fa65957395d7bb4))
### Bug Fixes
* **auth:** Allow non-default SA credentials for DP ([#11828](https://github.com/googleapis/google-cloud-go/issues/11828)) ([3a996b4](https://github.com/googleapis/google-cloud-go/commit/3a996b4129e6d0a34dfda6671f535d5aefb26a82))
* **auth:** Restore calling DialContext ([#11930](https://github.com/googleapis/google-cloud-go/issues/11930)) ([9ec9a29](https://github.com/googleapis/google-cloud-go/commit/9ec9a29494e93197edbaf45aba28984801e9770a)), refs [#11118](https://github.com/googleapis/google-cloud-go/issues/11118)
## [0.15.0](https://github.com/googleapis/google-cloud-go/compare/auth/v0.14.1...auth/v0.15.0) (2025-02-19)
### Features
* **auth:** Add hard-bound token request to compute token provider. ([#11588](https://github.com/googleapis/google-cloud-go/issues/11588)) ([0e608bb](https://github.com/googleapis/google-cloud-go/commit/0e608bb5ac3d694c8ad36ca4340071d3a2c78699))
## [0.14.1](https://github.com/googleapis/google-cloud-go/compare/auth/v0.14.0...auth/v0.14.1) (2025-01-24)
### Documentation
* **auth:** Add warning about externally-provided credentials ([#11462](https://github.com/googleapis/google-cloud-go/issues/11462)) ([49fb6ff](https://github.com/googleapis/google-cloud-go/commit/49fb6ff4d754895f82c9c4d502fc7547d3b5a941))
## [0.14.0](https://github.com/googleapis/google-cloud-go/compare/auth/v0.13.0...auth/v0.14.0) (2025-01-08)
### Features
* **auth:** Add universe domain support to idtoken ([#11059](https://github.com/googleapis/google-cloud-go/issues/11059)) ([72add7e](https://github.com/googleapis/google-cloud-go/commit/72add7e9f8f455af695e8ef79212a4bd3122fb3a))
### Bug Fixes
* **auth/oauth2adapt:** Update golang.org/x/net to v0.33.0 ([e9b0b69](https://github.com/googleapis/google-cloud-go/commit/e9b0b69644ea5b276cacff0a707e8a5e87efafc9))
* **auth:** Fix copy of delegates in impersonate.NewIDTokenCredentials ([#11386](https://github.com/googleapis/google-cloud-go/issues/11386)) ([ff7ef8e](https://github.com/googleapis/google-cloud-go/commit/ff7ef8e7ade7171bce3e4f30ff10a2e9f6c27ca0)), refs [#11379](https://github.com/googleapis/google-cloud-go/issues/11379)
* **auth:** Update golang.org/x/net to v0.33.0 ([e9b0b69](https://github.com/googleapis/google-cloud-go/commit/e9b0b69644ea5b276cacff0a707e8a5e87efafc9))
## [0.13.0](https://github.com/googleapis/google-cloud-go/compare/auth/v0.12.1...auth/v0.13.0) (2024-12-13)

View File

@@ -362,9 +362,6 @@ func (c *cachedTokenProvider) tokenState() tokenState {
// blocking call to Token should likely return the same error on the main goroutine.
func (c *cachedTokenProvider) tokenAsync(ctx context.Context) {
fn := func() {
c.mu.Lock()
c.isRefreshRunning = true
c.mu.Unlock()
t, err := c.tp.Token(ctx)
c.mu.Lock()
defer c.mu.Unlock()
@@ -380,6 +377,7 @@ func (c *cachedTokenProvider) tokenAsync(ctx context.Context) {
c.mu.Lock()
defer c.mu.Unlock()
if !c.isRefreshRunning && !c.isRefreshErr {
c.isRefreshRunning = true
go fn()
}
}

View File

@@ -39,8 +39,9 @@ var (
// uses the metadata service to retrieve tokens.
func computeTokenProvider(opts *DetectOptions, client *metadata.Client) auth.TokenProvider {
return auth.NewCachedTokenProvider(&computeProvider{
scopes: opts.Scopes,
client: client,
scopes: opts.Scopes,
client: client,
tokenBindingType: opts.TokenBindingType,
}, &auth.CachedTokenProviderOptions{
ExpireEarly: opts.EarlyTokenRefresh,
DisableAsyncRefresh: opts.DisableAsyncRefresh,
@@ -49,8 +50,9 @@ func computeTokenProvider(opts *DetectOptions, client *metadata.Client) auth.Tok
// computeProvider fetches tokens from the google cloud metadata service.
type computeProvider struct {
scopes []string
client *metadata.Client
scopes []string
client *metadata.Client
tokenBindingType TokenBindingType
}
type metadataTokenResp struct {
@@ -64,9 +66,19 @@ func (cs *computeProvider) Token(ctx context.Context) (*auth.Token, error) {
if err != nil {
return nil, err
}
if len(cs.scopes) > 0 {
hasScopes := len(cs.scopes) > 0
if hasScopes || cs.tokenBindingType != NoBinding {
v := url.Values{}
v.Set("scopes", strings.Join(cs.scopes, ","))
if hasScopes {
v.Set("scopes", strings.Join(cs.scopes, ","))
}
switch cs.tokenBindingType {
case MTLSHardBinding:
v.Set("transport", "mtls")
v.Set("binding-enforcement", "on")
case ALTSHardBinding:
v.Set("transport", "alts")
}
tokenURI.RawQuery = v.Encode()
}
tokenJSON, err := cs.client.GetWithContext(ctx, tokenURI.String())

View File

@@ -51,6 +51,23 @@ var (
allowOnGCECheck = true
)
// TokenBindingType specifies the type of binding used when requesting a token
// whether to request a hard-bound token using mTLS or an instance identity
// bound token using ALTS.
type TokenBindingType int
const (
// NoBinding specifies that requested tokens are not required to have a
// binding. This is the default option.
NoBinding TokenBindingType = iota
// MTLSHardBinding specifies that a hard-bound token should be requested
// using an mTLS with S2A channel.
MTLSHardBinding
// ALTSHardBinding specifies that an instance identity bound token should
// be requested using an ALTS channel.
ALTSHardBinding
)
// OnGCE reports whether this process is running in Google Cloud.
func OnGCE() bool {
// TODO(codyoss): once all libs use this auth lib move metadata check here
@@ -99,7 +116,8 @@ func DetectDefault(opts *DetectOptions) (*auth.Credentials, error) {
if OnGCE() {
metadataClient := metadata.NewWithOptions(&metadata.Options{
Logger: opts.logger(),
Logger: opts.logger(),
UseDefaultClient: true,
})
return auth.NewCredentials(&auth.CredentialsOptions{
TokenProvider: computeTokenProvider(opts, metadataClient),
@@ -121,6 +139,10 @@ type DetectOptions struct {
// https://www.googleapis.com/auth/cloud-platform. Required if Audience is
// not provided.
Scopes []string
// TokenBindingType specifies the type of binding used when requesting a
// token whether to request a hard-bound token using mTLS or an instance
// identity bound token using ALTS. Optional.
TokenBindingType TokenBindingType
// Audience that credentials tokens should have. Only applicable for 2LO
// flows with service accounts. If specified, scopes should not be provided.
Audience string
@@ -149,10 +171,26 @@ type DetectOptions struct {
// CredentialsFile overrides detection logic and sources a credential file
// from the provided filepath. If provided, CredentialsJSON must not be.
// Optional.
//
// Important: If you accept a credential configuration (credential
// JSON/File/Stream) from an external source for authentication to Google
// Cloud Platform, you must validate it before providing it to any Google
// API or library. Providing an unvalidated credential configuration to
// Google APIs can compromise the security of your systems and data. For
// more information, refer to [Validate credential configurations from
// external sources](https://cloud.google.com/docs/authentication/external/externally-sourced-credentials).
CredentialsFile string
// CredentialsJSON overrides detection logic and uses the JSON bytes as the
// source for the credential. If provided, CredentialsFile must not be.
// Optional.
//
// Important: If you accept a credential configuration (credential
// JSON/File/Stream) from an external source for authentication to Google
// Cloud Platform, you must validate it before providing it to any Google
// API or library. Providing an unvalidated credential configuration to
// Google APIs can compromise the security of your systems and data. For
// more information, refer to [Validate credential configurations from
// external sources](https://cloud.google.com/docs/authentication/external/externally-sourced-credentials).
CredentialsJSON []byte
// UseSelfSignedJWT directs service account based credentials to create a
// self-signed JWT with the private key found in the file, skipping any

View File

@@ -36,6 +36,8 @@ func fileCredentials(b []byte, opts *DetectOptions) (*auth.Credentials, error) {
var projectID, universeDomain string
var tp auth.TokenProvider
switch fileType {
case credsfile.UnknownCredType:
return nil, errors.New("credentials: unsupported unidentified file type")
case credsfile.ServiceAccountKey:
f, err := credsfile.ParseServiceAccount(b)
if err != nil {

View File

@@ -413,7 +413,10 @@ func newSubjectTokenProvider(o *Options) (subjectTokenProvider, error) {
if cert.UseDefaultCertificateConfig && cert.CertificateConfigLocation != "" {
return nil, errors.New("credentials: \"certificate\" object cannot specify both a certificate_config_location and use_default_certificate_config=true")
}
return &x509Provider{}, nil
return &x509Provider{
TrustChainPath: o.CredentialSource.Certificate.TrustChainPath,
ConfigFilePath: o.CredentialSource.Certificate.CertificateConfigLocation,
}, nil
}
return nil, errors.New("credentials: unable to parse credential source")
}

View File

@@ -17,27 +17,184 @@ package externalaccount
import (
"context"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
"io/fs"
"net/http"
"os"
"strings"
"time"
"cloud.google.com/go/auth/internal/transport/cert"
)
// x509Provider implements the subjectTokenProvider type for
// x509 workload identity credentials. Because x509 credentials
// rely on an mTLS connection to represent the 3rd party identity
// rather than a subject token, this provider will always return
// an empty string when a subject token is requested by the external account
// token provider.
// x509Provider implements the subjectTokenProvider type for x509 workload
// identity credentials. This provider retrieves and formats a JSON array
// containing the leaf certificate and trust chain (if provided) as
// base64-encoded strings. This JSON array serves as the subject token for
// mTLS authentication.
type x509Provider struct {
// TrustChainPath is the path to the file containing the trust chain certificates.
// The file should contain one or more PEM-encoded certificates.
TrustChainPath string
// ConfigFilePath is the path to the configuration file containing the path
// to the leaf certificate file.
ConfigFilePath string
}
const pemCertificateHeader = "-----BEGIN CERTIFICATE-----"
func (xp *x509Provider) providerType() string {
return x509ProviderType
}
func (xp *x509Provider) subjectToken(ctx context.Context) (string, error) {
return "", nil
// loadLeafCertificate loads and parses the leaf certificate from the specified
// configuration file. It retrieves the certificate path from the config file,
// reads the certificate file, and parses the certificate data.
func loadLeafCertificate(configFilePath string) (*x509.Certificate, error) {
// Get the path to the certificate file from the configuration file.
path, err := cert.GetCertificatePath(configFilePath)
if err != nil {
return nil, fmt.Errorf("failed to get certificate path from config file: %w", err)
}
leafCertBytes, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read leaf certificate file: %w", err)
}
// Parse the certificate bytes.
return parseCertificate(leafCertBytes)
}
// encodeCert encodes a x509.Certificate to a base64 string.
func encodeCert(cert *x509.Certificate) string {
// cert.Raw contains the raw DER-encoded certificate. Encode the raw certificate bytes to base64.
return base64.StdEncoding.EncodeToString(cert.Raw)
}
// parseCertificate parses a PEM-encoded certificate from the given byte slice.
func parseCertificate(certData []byte) (*x509.Certificate, error) {
if len(certData) == 0 {
return nil, errors.New("invalid certificate data: empty input")
}
// Decode the PEM-encoded data.
block, _ := pem.Decode(certData)
if block == nil {
return nil, errors.New("invalid PEM-encoded certificate data: no PEM block found")
}
if block.Type != "CERTIFICATE" {
return nil, fmt.Errorf("invalid PEM-encoded certificate data: expected CERTIFICATE block type, got %s", block.Type)
}
// Parse the DER-encoded certificate.
certificate, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse certificate: %w", err)
}
return certificate, nil
}
// readTrustChain reads a file of PEM-encoded X.509 certificates and returns a slice of parsed certificates.
// It splits the file content into PEM certificate blocks and parses each one.
func readTrustChain(trustChainPath string) ([]*x509.Certificate, error) {
certificateTrustChain := []*x509.Certificate{}
// If no trust chain path is provided, return an empty slice.
if trustChainPath == "" {
return certificateTrustChain, nil
}
// Read the trust chain file.
trustChainData, err := os.ReadFile(trustChainPath)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return nil, fmt.Errorf("trust chain file not found: %w", err)
}
return nil, fmt.Errorf("failed to read trust chain file: %w", err)
}
// Split the file content into PEM certificate blocks.
certBlocks := strings.Split(string(trustChainData), pemCertificateHeader)
// Iterate over each certificate block.
for _, certBlock := range certBlocks {
// Trim whitespace from the block.
certBlock = strings.TrimSpace(certBlock)
if certBlock != "" {
// Add the PEM header to the block.
certData := pemCertificateHeader + "\n" + certBlock
// Parse the certificate data.
cert, err := parseCertificate([]byte(certData))
if err != nil {
return nil, fmt.Errorf("error parsing certificate from trust chain file: %w", err)
}
// Append the certificate to the trust chain.
certificateTrustChain = append(certificateTrustChain, cert)
}
}
return certificateTrustChain, nil
}
// subjectToken retrieves the X.509 subject token. It loads the leaf
// certificate and, if a trust chain path is configured, the trust chain
// certificates. It then constructs a JSON array containing the base64-encoded
// leaf certificate and each base64-encoded certificate in the trust chain.
// The leaf certificate must be at the top of the trust chain file. This JSON
// array is used as the subject token for mTLS authentication.
func (xp *x509Provider) subjectToken(context.Context) (string, error) {
// Load the leaf certificate.
leafCert, err := loadLeafCertificate(xp.ConfigFilePath)
if err != nil {
return "", fmt.Errorf("failed to load leaf certificate: %w", err)
}
// Read the trust chain.
trustChain, err := readTrustChain(xp.TrustChainPath)
if err != nil {
return "", fmt.Errorf("failed to read trust chain: %w", err)
}
// Initialize the certificate chain with the leaf certificate.
certChain := []string{encodeCert(leafCert)}
// If there is a trust chain, add certificates to the certificate chain.
if len(trustChain) > 0 {
firstCert := encodeCert(trustChain[0])
// If the first certificate in the trust chain is not the same as the leaf certificate, add it to the chain.
if firstCert != certChain[0] {
certChain = append(certChain, firstCert)
}
// Iterate over the remaining certificates in the trust chain.
for i := 1; i < len(trustChain); i++ {
encoded := encodeCert(trustChain[i])
// Return an error if the current certificate is the same as the leaf certificate.
if encoded == certChain[0] {
return "", errors.New("the leaf certificate must be at the top of the trust chain file")
}
// Add the current certificate to the chain.
certChain = append(certChain, encoded)
}
}
// Convert the certificate chain to a JSON array of base64-encoded strings.
jsonChain, err := json.Marshal(certChain)
if err != nil {
return "", fmt.Errorf("failed to format certificate data: %w", err)
}
// Return the JSON-formatted certificate chain.
return string(jsonChain), nil
}
// createX509Client creates a new client that is configured with mTLS, using the

View File

@@ -0,0 +1,105 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package impersonate
import (
"bytes"
"context"
"encoding/json"
"fmt"
"log/slog"
"net/http"
"strings"
"time"
"cloud.google.com/go/auth"
"cloud.google.com/go/auth/internal"
"github.com/googleapis/gax-go/v2/internallog"
)
var (
universeDomainPlaceholder = "UNIVERSE_DOMAIN"
iamCredentialsUniverseDomainEndpoint = "https://iamcredentials.UNIVERSE_DOMAIN"
)
// IDTokenIAMOptions provides configuration for [IDTokenIAMOptions.Token].
type IDTokenIAMOptions struct {
// Client is required.
Client *http.Client
// Logger is required.
Logger *slog.Logger
UniverseDomain auth.CredentialsPropertyProvider
ServiceAccountEmail string
GenerateIDTokenRequest
}
// GenerateIDTokenRequest holds the request to the IAM generateIdToken RPC.
type GenerateIDTokenRequest struct {
Audience string `json:"audience"`
IncludeEmail bool `json:"includeEmail"`
// Delegates are the ordered, fully-qualified resource name for service
// accounts in a delegation chain. Each service account must be granted
// roles/iam.serviceAccountTokenCreator on the next service account in the
// chain. The delegates must have the following format:
// projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}. The - wildcard
// character is required; replacing it with a project ID is invalid.
// Optional.
Delegates []string `json:"delegates,omitempty"`
}
// GenerateIDTokenResponse holds the response from the IAM generateIdToken RPC.
type GenerateIDTokenResponse struct {
Token string `json:"token"`
}
// Token call IAM generateIdToken with the configuration provided in [IDTokenIAMOptions].
func (o IDTokenIAMOptions) Token(ctx context.Context) (*auth.Token, error) {
universeDomain, err := o.UniverseDomain.GetProperty(ctx)
if err != nil {
return nil, err
}
endpoint := strings.Replace(iamCredentialsUniverseDomainEndpoint, universeDomainPlaceholder, universeDomain, 1)
url := fmt.Sprintf("%s/v1/%s:generateIdToken", endpoint, internal.FormatIAMServiceAccountResource(o.ServiceAccountEmail))
bodyBytes, err := json.Marshal(o.GenerateIDTokenRequest)
if err != nil {
return nil, fmt.Errorf("impersonate: unable to marshal request: %w", err)
}
req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(bodyBytes))
if err != nil {
return nil, fmt.Errorf("impersonate: unable to create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
o.Logger.DebugContext(ctx, "impersonated idtoken request", "request", internallog.HTTPRequest(req, bodyBytes))
resp, body, err := internal.DoRequest(o.Client, req)
if err != nil {
return nil, fmt.Errorf("impersonate: unable to generate ID token: %w", err)
}
o.Logger.DebugContext(ctx, "impersonated idtoken response", "response", internallog.HTTPResponse(resp, body))
if c := resp.StatusCode; c < 200 || c > 299 {
return nil, fmt.Errorf("impersonate: status code %d: %s", c, body)
}
var tokenResp GenerateIDTokenResponse
if err := json.Unmarshal(body, &tokenResp); err != nil {
return nil, fmt.Errorf("impersonate: unable to parse response: %w", err)
}
return &auth.Token{
Value: tokenResp.Token,
// Generated ID tokens are good for one hour.
Expiry: time.Now().Add(1 * time.Hour),
}, nil
}

View File

@@ -20,13 +20,18 @@ import (
"os"
"strconv"
"strings"
"time"
"cloud.google.com/go/auth"
"cloud.google.com/go/auth/credentials"
"cloud.google.com/go/auth/internal/compute"
"golang.org/x/time/rate"
"google.golang.org/grpc"
grpcgoogle "google.golang.org/grpc/credentials/google"
)
var logRateLimiter = rate.Sometimes{Interval: 1 * time.Second}
func isDirectPathEnabled(endpoint string, opts *Options) bool {
if opts.InternalOptions != nil && !opts.InternalOptions.EnableDirectPath {
return false
@@ -55,7 +60,7 @@ func checkDirectPathEndPoint(endpoint string) bool {
return true
}
func isTokenProviderDirectPathCompatible(tp auth.TokenProvider, o *Options) bool {
func isTokenProviderComputeEngine(tp auth.TokenProvider) bool {
if tp == nil {
return false
}
@@ -69,15 +74,22 @@ func isTokenProviderDirectPathCompatible(tp auth.TokenProvider, o *Options) bool
if tok.MetadataString("auth.google.tokenSource") != "compute-metadata" {
return false
}
if o.InternalOptions != nil && o.InternalOptions.EnableNonDefaultSAForDirectPath {
return true
}
if tok.MetadataString("auth.google.serviceAccount") != "default" {
return false
}
return true
}
func isTokenProviderDirectPathCompatible(tp auth.TokenProvider, o *Options) bool {
if tp == nil {
return false
}
if o.InternalOptions != nil && o.InternalOptions.EnableNonDefaultSAForDirectPath {
return true
}
return isTokenProviderComputeEngine(tp)
}
func isDirectPathXdsUsed(o *Options) bool {
// Method 1: Enable DirectPath xDS by env;
if b, _ := strconv.ParseBool(os.Getenv(enableDirectPathXdsEnvVar)); b {
@@ -90,14 +102,36 @@ func isDirectPathXdsUsed(o *Options) bool {
return false
}
func isDirectPathBoundTokenEnabled(opts *InternalOptions) bool {
for _, ev := range opts.AllowHardBoundTokens {
if ev == "ALTS" {
return true
}
}
return false
}
// configureDirectPath returns some dial options and an endpoint to use if the
// configuration allows the use of direct path. If it does not the provided
// grpcOpts and endpoint are returned.
func configureDirectPath(grpcOpts []grpc.DialOption, opts *Options, endpoint string, creds *auth.Credentials) ([]grpc.DialOption, string) {
func configureDirectPath(grpcOpts []grpc.DialOption, opts *Options, endpoint string, creds *auth.Credentials) ([]grpc.DialOption, string, error) {
logRateLimiter.Do(func() {
logDirectPathMisconfig(endpoint, creds, opts)
})
if isDirectPathEnabled(endpoint, opts) && compute.OnComputeEngine() && isTokenProviderDirectPathCompatible(creds, opts) {
// Overwrite all of the previously specific DialOptions, DirectPath uses its own set of credentials and certificates.
defaultCredetialsOptions := grpcgoogle.DefaultCredentialsOptions{PerRPCCreds: &grpcCredentialsProvider{creds: creds}}
if isDirectPathBoundTokenEnabled(opts.InternalOptions) && isTokenProviderComputeEngine(creds) {
optsClone := opts.resolveDetectOptions()
optsClone.TokenBindingType = credentials.ALTSHardBinding
altsCreds, err := credentials.DetectDefault(optsClone)
if err != nil {
return nil, "", err
}
defaultCredetialsOptions.ALTSPerRPCCreds = &grpcCredentialsProvider{creds: altsCreds}
}
grpcOpts = []grpc.DialOption{
grpc.WithCredentialsBundle(grpcgoogle.NewDefaultCredentialsWithOptions(grpcgoogle.DefaultCredentialsOptions{PerRPCCreds: &grpcCredentialsProvider{creds: creds}}))}
grpc.WithCredentialsBundle(grpcgoogle.NewDefaultCredentialsWithOptions(defaultCredetialsOptions))}
if timeoutDialerOption != nil {
grpcOpts = append(grpcOpts, timeoutDialerOption)
}
@@ -122,5 +156,22 @@ func configureDirectPath(grpcOpts []grpc.DialOption, opts *Options, endpoint str
}
// TODO: add support for system parameters (quota project, request reason) via chained interceptor.
}
return grpcOpts, endpoint
return grpcOpts, endpoint, nil
}
func logDirectPathMisconfig(endpoint string, creds *auth.Credentials, o *Options) {
// Case 1: does not enable DirectPath
if !isDirectPathEnabled(endpoint, o) {
o.logger().Warn("DirectPath is disabled. To enable, please set the EnableDirectPath option along with the EnableDirectPathXds option.")
} else {
// Case 2: credential is not correctly set
if !isTokenProviderDirectPathCompatible(creds, o) {
o.logger().Warn("DirectPath is disabled. Please make sure the token source is fetched from GCE metadata server and the default service account is used.")
}
// Case 3: not running on GCE
if !compute.OnComputeEngine() {
o.logger().Warn("DirectPath is disabled. DirectPath is only available in a GCE environment.")
}
}
}

View File

@@ -204,6 +204,10 @@ type InternalOptions struct {
EnableDirectPathXds bool
// EnableJWTWithScope specifies if scope can be used with self-signed JWT.
EnableJWTWithScope bool
// AllowHardBoundTokens allows libraries to request a hard-bound token.
// Obtaining hard-bound tokens requires the connection to be established
// using either ALTS or mTLS with S2A.
AllowHardBoundTokens []string
// DefaultAudience specifies a default audience to be used as the audience
// field ("aud") for the JWT token authentication.
DefaultAudience string
@@ -262,13 +266,13 @@ func dial(ctx context.Context, secure bool, opts *Options) (*grpc.ClientConn, er
tOpts.EnableDirectPath = io.EnableDirectPath
tOpts.EnableDirectPathXds = io.EnableDirectPathXds
}
transportCreds, endpoint, err := transport.GetGRPCTransportCredsAndEndpoint(tOpts)
transportCreds, err := transport.GetGRPCTransportCredsAndEndpoint(tOpts)
if err != nil {
return nil, err
}
if !secure {
transportCreds = grpcinsecure.NewCredentials()
transportCreds.TransportCredentials = grpcinsecure.NewCredentials()
}
// Initialize gRPC dial options with transport-level security options.
@@ -297,8 +301,21 @@ func dial(ctx context.Context, secure bool, opts *Options) (*grpc.ClientConn, er
if opts.Credentials != nil {
creds = opts.Credentials
} else {
// This condition is only met for non-DirectPath clients because
// TransportTypeMTLSS2A is used only when InternalOptions.EnableDirectPath
// is false.
optsClone := opts.resolveDetectOptions()
if transportCreds.TransportType == transport.TransportTypeMTLSS2A {
// Check that the client allows requesting hard-bound token for the transport type mTLS using S2A.
for _, ev := range opts.InternalOptions.AllowHardBoundTokens {
if ev == "MTLS_S2A" {
optsClone.TokenBindingType = credentials.MTLSHardBinding
break
}
}
}
var err error
creds, err = credentials.DetectDefault(opts.resolveDetectOptions())
creds, err = credentials.DetectDefault(optsClone)
if err != nil {
return nil, err
}
@@ -324,9 +341,11 @@ func dial(ctx context.Context, secure bool, opts *Options) (*grpc.ClientConn, er
clientUniverseDomain: opts.UniverseDomain,
}),
)
// Attempt Direct Path
grpcOpts, endpoint = configureDirectPath(grpcOpts, opts, endpoint, creds)
grpcOpts, transportCreds.Endpoint, err = configureDirectPath(grpcOpts, opts, transportCreds.Endpoint, creds)
if err != nil {
return nil, err
}
}
// Add tracing, but before the other options, so that clients can override the
@@ -335,7 +354,7 @@ func dial(ctx context.Context, secure bool, opts *Options) (*grpc.ClientConn, er
grpcOpts = addOpenTelemetryStatsHandler(grpcOpts, opts)
grpcOpts = append(grpcOpts, opts.GRPCDialOpts...)
return grpc.Dial(endpoint, grpcOpts...)
return grpc.DialContext(ctx, transportCreds.Endpoint, grpcOpts...)
}
// grpcKeyProvider satisfies https://pkg.go.dev/google.golang.org/grpc/credentials#PerRPCCredentials.

View File

@@ -127,6 +127,7 @@ type ExecutableConfig struct {
type CertificateConfig struct {
UseDefaultCertificateConfig bool `json:"use_default_certificate_config"`
CertificateConfigLocation string `json:"certificate_config_location"`
TrustChainPath string `json:"trust_chain_path"`
}
// ServiceAccountImpersonationInfo has impersonation configuration.

View File

@@ -217,3 +217,9 @@ func getMetadataUniverseDomain(ctx context.Context, client *metadata.Client) (st
}
return "", err
}
// FormatIAMServiceAccountResource sets a service account name in an IAM resource
// name.
func FormatIAMServiceAccountResource(name string) string {
return fmt.Sprintf("projects/-/serviceAccounts/%s", name)
}

View File

@@ -31,7 +31,6 @@ import (
"cloud.google.com/go/auth/internal"
"cloud.google.com/go/auth/internal/transport/cert"
"github.com/google/s2a-go"
"github.com/google/s2a-go/fallback"
"google.golang.org/grpc/credentials"
)
@@ -52,6 +51,16 @@ const (
mtlsMDSKey = "/run/google-mds-mtls/client.key"
)
// Type represents the type of transport used.
type Type int
const (
// TransportTypeUnknown represents an unknown transport type and is the default option.
TransportTypeUnknown Type = iota
// TransportTypeMTLSS2A represents the mTLS transport type using S2A.
TransportTypeMTLSS2A
)
// Options is a struct that is duplicated information from the individual
// transport packages in order to avoid cyclic deps. It correlates 1:1 with
// fields on httptransport.Options and grpctransport.Options.
@@ -120,13 +129,20 @@ func fixScheme(baseURL string) string {
return baseURL
}
// GRPCTransportCredentials embeds interface TransportCredentials with additional data.
type GRPCTransportCredentials struct {
credentials.TransportCredentials
Endpoint string
TransportType Type
}
// GetGRPCTransportCredsAndEndpoint returns an instance of
// [google.golang.org/grpc/credentials.TransportCredentials], and the
// corresponding endpoint to use for GRPC client.
func GetGRPCTransportCredsAndEndpoint(opts *Options) (credentials.TransportCredentials, string, error) {
// corresponding endpoint and transport type to use for GRPC client.
func GetGRPCTransportCredsAndEndpoint(opts *Options) (*GRPCTransportCredentials, error) {
config, err := getTransportConfig(opts)
if err != nil {
return nil, "", err
return nil, err
}
defaultTransportCreds := credentials.NewTLS(&tls.Config{
@@ -144,33 +160,24 @@ func GetGRPCTransportCredsAndEndpoint(opts *Options) (credentials.TransportCrede
if config.s2aAddress != "" {
s2aAddr = config.s2aAddress
} else {
return defaultTransportCreds, config.endpoint, nil
return &GRPCTransportCredentials{defaultTransportCreds, config.endpoint, TransportTypeUnknown}, nil
}
}
} else if config.s2aAddress != "" {
s2aAddr = config.s2aAddress
} else {
return defaultTransportCreds, config.endpoint, nil
}
var fallbackOpts *s2a.FallbackOptions
// In case of S2A failure, fall back to the endpoint that would've been used without S2A.
if fallbackHandshake, err := fallback.DefaultFallbackClientHandshakeFunc(config.endpoint); err == nil {
fallbackOpts = &s2a.FallbackOptions{
FallbackClientHandshakeFunc: fallbackHandshake,
}
return &GRPCTransportCredentials{defaultTransportCreds, config.endpoint, TransportTypeUnknown}, nil
}
s2aTransportCreds, err := s2a.NewClientCreds(&s2a.ClientOptions{
S2AAddress: s2aAddr,
TransportCreds: transportCredsForS2A,
FallbackOpts: fallbackOpts,
})
if err != nil {
// Use default if we cannot initialize S2A client transport credentials.
return defaultTransportCreds, config.endpoint, nil
return &GRPCTransportCredentials{defaultTransportCreds, config.endpoint, TransportTypeUnknown}, nil
}
return s2aTransportCreds, config.s2aMTLSEndpoint, nil
return &GRPCTransportCredentials{s2aTransportCreds, config.s2aMTLSEndpoint, TransportTypeMTLSS2A}, nil
}
// GetHTTPTransportConfig returns a client certificate source and a function for
@@ -201,23 +208,9 @@ func GetHTTPTransportConfig(opts *Options) (cert.Provider, func(context.Context,
return config.clientCertSource, nil, nil
}
var fallbackOpts *s2a.FallbackOptions
// In case of S2A failure, fall back to the endpoint that would've been used without S2A.
if fallbackURL, err := url.Parse(config.endpoint); err == nil {
if fallbackDialer, fallbackServerAddr, err := fallback.DefaultFallbackDialerAndAddress(fallbackURL.Hostname()); err == nil {
fallbackOpts = &s2a.FallbackOptions{
FallbackDialer: &s2a.FallbackDialer{
Dialer: fallbackDialer,
ServerAddr: fallbackServerAddr,
},
}
}
}
dialTLSContextFunc := s2a.NewS2ADialTLSContextFunc(&s2a.ClientOptions{
S2AAddress: s2aAddr,
TransportCreds: transportCredsForS2A,
FallbackOpts: fallbackOpts,
})
return nil, dialTLSContextFunc, nil
}

View File

@@ -37,6 +37,36 @@ type certificateConfig struct {
CertConfigs certConfigs `json:"cert_configs"`
}
// getconfigFilePath determines the path to the certificate configuration file.
// It first checks for the presence of an environment variable that specifies
// the file path. If the environment variable is not set, it falls back to
// a default configuration file path.
func getconfigFilePath() string {
envFilePath := util.GetConfigFilePathFromEnv()
if envFilePath != "" {
return envFilePath
}
return util.GetDefaultConfigFilePath()
}
// GetCertificatePath retrieves the certificate file path from the provided
// configuration file. If the configFilePath is empty, it attempts to load
// the configuration from a well-known gcloud location.
// This function is exposed to allow other packages, such as the
// externalaccount package, to retrieve the certificate path without needing
// to load the entire certificate configuration.
func GetCertificatePath(configFilePath string) (string, error) {
if configFilePath == "" {
configFilePath = getconfigFilePath()
}
certFile, _, err := getCertAndKeyFiles(configFilePath)
if err != nil {
return "", err
}
return certFile, nil
}
// NewWorkloadX509CertProvider creates a certificate source
// that reads a certificate and private key file from the local file system.
// This is intended to be used for workload identity federation.
@@ -47,14 +77,8 @@ type certificateConfig struct {
// a well-known gcloud location.
func NewWorkloadX509CertProvider(configFilePath string) (Provider, error) {
if configFilePath == "" {
envFilePath := util.GetConfigFilePathFromEnv()
if envFilePath != "" {
configFilePath = envFilePath
} else {
configFilePath = util.GetDefaultConfigFilePath()
}
configFilePath = getconfigFilePath()
}
certFile, keyFile, err := getCertAndKeyFiles(configFilePath)
if err != nil {
return nil, err

View File

@@ -37,6 +37,7 @@ func CloneDetectOptions(oldDo *credentials.DetectOptions) *credentials.DetectOpt
}
newDo := &credentials.DetectOptions{
// Simple types
TokenBindingType: oldDo.TokenBindingType,
Audience: oldDo.Audience,
Subject: oldDo.Subject,
EarlyTokenRefresh: oldDo.EarlyTokenRefresh,
@@ -46,8 +47,8 @@ func CloneDetectOptions(oldDo *credentials.DetectOptions) *credentials.DetectOpt
UseSelfSignedJWT: oldDo.UseSelfSignedJWT,
UniverseDomain: oldDo.UniverseDomain,
// These fields are are pointer types that we just want to use exactly
// as the user set, copy the ref
// These fields are pointer types that we just want to use exactly as
// the user set, copy the ref
Client: oldDo.Client,
Logger: oldDo.Logger,
AuthHandlerOptions: oldDo.AuthHandlerOptions,

View File

@@ -1,5 +1,19 @@
# Changelog
## [0.2.8](https://github.com/googleapis/google-cloud-go/compare/auth/oauth2adapt/v0.2.7...auth/oauth2adapt/v0.2.8) (2025-03-17)
### Bug Fixes
* **auth/oauth2adapt:** Update golang.org/x/net to 0.37.0 ([1144978](https://github.com/googleapis/google-cloud-go/commit/11449782c7fb4896bf8b8b9cde8e7441c84fb2fd))
## [0.2.7](https://github.com/googleapis/google-cloud-go/compare/auth/oauth2adapt/v0.2.6...auth/oauth2adapt/v0.2.7) (2025-01-09)
### Bug Fixes
* **auth/oauth2adapt:** Update golang.org/x/net to v0.33.0 ([e9b0b69](https://github.com/googleapis/google-cloud-go/commit/e9b0b69644ea5b276cacff0a707e8a5e87efafc9))
## [0.2.6](https://github.com/googleapis/google-cloud-go/compare/auth/oauth2adapt/v0.2.5...auth/oauth2adapt/v0.2.6) (2024-11-21)

139
vendor/cloud.google.com/go/debug.md generated vendored
View File

@@ -24,6 +24,17 @@ impact and are therefore not recommended for sustained production use. Use these
tips locally or in production for a *limited time* to help get a better
understanding of what is going on.
### Request/Response Logging
To enable logging for all outgoing requests from the Go Client Libraries, set
the environment variable `GOOGLE_SDK_GO_LOGGING_LEVEL` to `debug`. Currently all
logging is at the debug level, but this is likely to change in the future.
*Caution*: Debug level logging should only be used in a limited manner. Debug
level logs contain sensitive information, including headers, request/response
payloads, and authentication tokens. Additionally, enabling logging at this
level will have a minor performance impact.
### HTTP based clients
All of our auto-generated clients have a constructor to create a client that
@@ -40,74 +51,6 @@ GODEBUG=http2debug=1. To read more about this feature please see the godoc for
*WARNING*: Enabling this debug variable will log headers and payloads which may
contain private information.
#### Add in your own logging with an HTTP middleware
You may want to add in your own logging around HTTP requests. One way to do this
is to register a custom HTTP client with a logging transport built in. Here is
an example of how you would do this with the storage client.
*WARNING*: Adding this middleware will log headers and payloads which may
contain private information.
```go
package main
import (
"context"
"fmt"
"log"
"net/http"
"net/http/httputil"
"cloud.google.com/go/storage"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
htransport "google.golang.org/api/transport/http"
)
type loggingRoundTripper struct {
rt http.RoundTripper
}
func (d loggingRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
// Will create a dump of the request and body.
dump, err := httputil.DumpRequest(r, true)
if err != nil {
log.Println("error dumping request")
}
log.Printf("%s", dump)
return d.rt.RoundTrip(r)
}
func main() {
ctx := context.Background()
// Create a transport with authentication built-in detected with
// [ADC](https://google.aip.dev/auth/4110). Note you will have to pass any
// required scoped for the client you are using.
trans, err := htransport.NewTransport(ctx,
http.DefaultTransport,
option.WithScopes(storage.ScopeFullControl),
)
if err != nil {
log.Fatal(err)
}
// Embed customized transport into an HTTP client.
hc := &http.Client{
Transport: loggingRoundTripper{rt: trans},
}
// Supply custom HTTP client for use by the library.
client, err := storage.NewClient(ctx, option.WithHTTPClient(hc))
if err != nil {
log.Fatal(err)
}
defer client.Close()
// Use the client
}
```
### gRPC based clients
#### Try setting grpc-go's debug variables
@@ -117,66 +60,6 @@ Try setting the following environment variables for grpc-go:
good for diagnosing connection level failures. For more information please see
[grpc-go's debug documentation](https://pkg.go.dev/google.golang.org/grpc/examples/features/debugging#section-readme).
#### Add in your own logging with a gRPC interceptors
You may want to add in your own logging around gRPC requests. One way to do this
is to register a custom interceptor that adds logging. Here is
an example of how you would do this with the secretmanager client. Note this
example registers a UnaryClientInterceptor but you may want/need to register
a StreamClientInterceptor instead-of/as-well depending on what kinds of
RPCs you are calling.
*WARNING*: Adding this interceptor will log metadata and payloads which may
contain private information.
```go
package main
import (
"context"
"log"
secretmanager "cloud.google.com/go/secretmanager/apiv1"
"google.golang.org/api/option"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/reflect/protoreflect"
)
func loggingUnaryInterceptor() grpc.UnaryClientInterceptor {
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
err := invoker(ctx, method, req, reply, cc, opts...)
log.Printf("Invoked method: %v", method)
md, ok := metadata.FromOutgoingContext(ctx)
if ok {
log.Println("Metadata:")
for k, v := range md {
log.Printf("Key: %v, Value: %v", k, v)
}
}
reqb, merr := protojson.Marshal(req.(protoreflect.ProtoMessage))
if merr == nil {
log.Printf("Request: %s", reqb)
}
return err
}
}
func main() {
ctx := context.Background()
// Supply custom gRPC interceptor for use by the client.
client, err := secretmanager.NewClient(ctx,
option.WithGRPCDialOption(grpc.WithUnaryInterceptor(loggingUnaryInterceptor())),
)
if err != nil {
log.Fatal(err)
}
defer client.Close()
// Use the client
}
```
## Telemetry
**Warning: The OpenCensus project is obsolete and was archived on July 31st,

20
vendor/cloud.google.com/go/go.work generated vendored
View File

@@ -1,6 +1,4 @@
go 1.21.13
toolchain go1.23.0
go 1.23.0
use (
.
@@ -31,12 +29,14 @@ use (
./batch
./beyondcorp
./bigquery
./bigquery/v2
./bigtable
./billing
./binaryauthorization
./certificatemanager
./channel
./chat
./chronicle
./cloudbuild
./cloudcontrolspartner
./clouddms
@@ -48,6 +48,7 @@ use (
./compute/metadata
./confidentialcomputing
./config
./configdelivery
./contactcenterinsights
./container
./containeranalysis
@@ -63,6 +64,7 @@ use (
./datastream
./deploy
./developerconnect
./devicestreaming
./dialogflow
./discoveryengine
./dlp
@@ -74,6 +76,7 @@ use (
./essentialcontacts
./eventarc
./filestore
./financialservices
./firestore
./functions
./gkebackup
@@ -95,21 +98,27 @@ use (
./internal/gapicgen
./internal/generated/snippets
./internal/godocfx
./internal/librariangen
./internal/postprocessor
./internal/protoveneer
./iot
./kms
./language
./licensemanager
./lifesciences
./logging
./longrunning
./lustre
./maintenance
./managedidentities
./managedkafka
./maps
./mediatranslation
./memcache
./memorystore
./metastore
./migrationcenter
./modelarmor
./monitoring
./netapp
./networkconnectivity
@@ -124,6 +133,7 @@ use (
./osconfig
./oslogin
./parallelstore
./parametermanager
./phishingprotection
./policysimulator
./policytroubleshooter
@@ -131,6 +141,7 @@ use (
./privilegedaccessmanager
./profiler
./pubsub
./pubsub/v2
./pubsublite
./rapidmigrationassessment
./recaptchaenterprise
@@ -138,7 +149,6 @@ use (
./recommender
./redis
./resourcemanager
./resourcesettings
./retail
./run
./scheduler
@@ -156,10 +166,12 @@ use (
./shell
./shopping
./spanner
./spanner/benchmarks
./spanner/test/opentelemetry/test
./speech
./storage
./storage/internal/benchmarks
./storagebatchoperations
./storageinsights
./storagetransfer
./streetview

View File

@@ -2,99 +2,265 @@ cloud.google.com/go/auth v0.2.0/go.mod h1:+yb+oy3/P0geX6DLKlqiGHARGR6EX2GRtYCzWO
cloud.google.com/go/auth/oauth2adapt v0.2.0/go.mod h1:AfqujpDAlTfLfeCIl/HJZZlIxD8+nJoZ5e0x1IxGq5k=
cloud.google.com/go/dataproc v1.12.0 h1:W47qHL3W4BPkAIbk4SWmIERwsWBaNnWm0P2sdx3YgGU=
cloud.google.com/go/gaming v1.9.0 h1:7vEhFnZmd931Mo7sZ6pJy7uQPDxF7m7v8xtBheG08tc=
cloud.google.com/go/gaming v1.10.1 h1:5qZmZEWzMf8GEFgm9NeC3bjFRpt7x4S6U7oLbxaf7N8=
cloud.google.com/go/resourcesettings v1.8.3 h1:13HOFU7v4cEvIHXSAQbinF4wp2Baybbq7q9FMctg1Ek=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY=
gioui.org v0.0.0-20210308172011-57750fc8a0a6 h1:K72hopUosKG3ntOPNG4OzzbuhxGuVf06fa2la1/H/Ho=
git.sr.ht/~sbinet/gg v0.3.1 h1:LNhjNn8DerC8f9DHLz6lS0YYul/b602DUxDgGkd/Aik=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.18.0 h1:ugYJK/neZQtQeh2jc5xNoDFiMQojlAkoqJMRb7vTu1U=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.18.0/go.mod h1:Xx0VKh7GJ4si3rmElbh19Mejxz68ibWg/J30ZOMrqzU=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.23.0/go.mod h1:p2puVVSKjQ84Qb1gzw2XHLs34WQyHTYFZLaVxypAFYs=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.0/go.mod h1:p2puVVSKjQ84Qb1gzw2XHLs34WQyHTYFZLaVxypAFYs=
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9 h1:7kQgkwGRoLzC9K0oyXdJo7nve/bynv/KwUsxbiTlzAM=
github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19 h1:iXUgAaqDcIUGbRoy2TdeofRG/j1zpGRSEmNK05T+bi8=
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw=
github.com/alecthomas/assert/v2 v2.3.0 h1:mAsH2wmvjsuvyBvAmCtm7zFsBlb8mIHx5ySLVdDZXL0=
github.com/alecthomas/participle/v2 v2.1.0 h1:z7dElHRrOEEq45F2TG5cbQihMtNTv8vwldytDj7Wrz4=
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
github.com/apache/arrow/go/v12 v12.0.0 h1:xtZE63VWl7qLdB0JObIXvvhGjoVNrQ9ciIHG2OK5cmc=
github.com/apache/thrift v0.17.0 h1:cMd2aj52n+8VoAtvSvLn4kDC3aZ6IAkBuqWQ2IDu7wo=
github.com/aws/aws-sdk-go-v2 v1.16.10 h1:+yDD0tcuHRQZgqONkpDwzepqmElQaSlFPymHRHR9mrc=
github.com/aws/aws-sdk-go-v2 v1.16.10/go.mod h1:WTACcleLz6VZTp7fak4EO5b9Q4foxbn+8PIz3PmyKlo=
github.com/aws/aws-sdk-go-v2/config v1.15.9 h1:TK5yNEnFDQ9iaO04gJS/3Y+eW8BioQiCUafW75/Wc3Q=
github.com/aws/aws-sdk-go-v2/config v1.15.9/go.mod h1:rv/l/TbZo67kp99v/3Kb0qV6Fm1KEtKyruEV2GvVfgs=
github.com/aws/aws-sdk-go-v2/credentials v1.12.12 h1:iShu6VaWZZZfUZvlGtRjl+g1lWk44g1QmiCTD4KS0jI=
github.com/aws/aws-sdk-go-v2/credentials v1.12.12/go.mod h1:vFHC2HifIWHebmoVsfpqliKuqbAY2LaVlvy03JzF4c4=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.11 h1:zZHPdM2x09/0F8D7XyVvQnP2/jaW7bEMmtcSCPYq/iI=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.11/go.mod h1:38Asv/UyQbDNpSXCurZRlDMjzIl6J+wUe8vY3TtUuzA=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.17 h1:U8DZvyFFesBmK62dYC6BRXm4Cd/wPP3aPcecu3xv/F4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.17/go.mod h1:6qtGip7sJEyvgsLjphRZWF9qPe3xJf1mL/MM01E35Wc=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.11 h1:GMp98usVW5tzQhxd26KWhoNQPlR2noIlfbzqjVGBhLU=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.11/go.mod h1:cYAfnB+9ZkmZWpQWmPDsuIGm4EA+6k2ZVtxKjw/XJBY=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.18 h1:/spg6h3tG4pefphbvhpgdMtFMegSajPPSEJd1t8lnpc=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.18/go.mod h1:hTHq8hL4bAxJyng364s9d4IUGXZOs7Y5LSqAhIiIQ2A=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.18.3 h1:PK6c4wYv3wbb88eH0X0FjJwRykEoJwAesuslNReY7iE=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.18.3/go.mod h1:BrAJyOMrnwzYVQcP5ziqlCpnEuFfkNppZLzqDyW/YTg=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.11 h1:GkYtp4gi4wdWUV+pPetjk5y2aDxbr0t8n5OjVBwZdII=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.11/go.mod h1:OEofCUKF7Hri4ShOCokF6k6hGq9PCB2sywt/9rLSXjY=
github.com/aws/aws-sdk-go-v2/service/sso v1.11.15 h1:HaIE5/TtKr66qZTJpvMifDxH4lRt2JZawbkLYOo1F+Y=
github.com/aws/aws-sdk-go-v2/service/sso v1.11.15/go.mod h1:dDVD4ElJRTQXx7dOQ59EkqGyNU9tnwy1RKln+oLIOTU=
github.com/aws/aws-sdk-go-v2/service/sts v1.16.12 h1:YU9UHPukkCCnETHEExOptF/BxPvGJKXO/NBx+RMQ/2A=
github.com/aws/aws-sdk-go-v2/service/sts v1.16.12/go.mod h1:b53qpmhHk7mTL2J/tfG6f38neZiyBQSiNXGCuNKq4+4=
github.com/aws/smithy-go v1.12.1 h1:yQRC55aXN/y1W10HgwHle01DRuV9Dpf31iGkotjt3Ag=
github.com/aws/smithy-go v1.12.1/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/bazelbuild/rules_go v0.49.0/go.mod h1:Dhcz716Kqg1RHNWos+N6MlXNkjNP2EwZQ0LukRKJfMs=
github.com/bazelbuild/rules_go v0.49.0 h1:5vCbuvy8Q11g41lseGJDc5vxhDjJtfxr6nM/IC4VmqM=
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
github.com/bwesterb/go-ristretto v1.2.3 h1:1w53tCkGhCQ5djbat3+MH0BAQ5Kfgbt56UZQ/JMzngw=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
github.com/chzyer/logex v1.2.0 h1:+eqR0HfOetur4tgnC8ftU5imRnhi4te+BadWS95c5AM=
github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
github.com/chzyer/test v0.0.0-20210722231415-061457976a23 h1:dZ0/VyGgQdVGAss6Ju0dt5P0QltE0SFY5Woh6hbIfiQ=
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk=
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
github.com/fullstorydev/grpcurl v1.8.7 h1:xJWosq3BQovQ4QrdPO72OrPiWuGgEsxY8ldYsJbPrqI=
github.com/fullstorydev/grpcurl v1.8.7/go.mod h1:pVtM4qe3CMoLaIzYS8uvTuDj2jVYmXqMUkZeijnXp/E=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/go-fonts/dejavu v0.1.0 h1:JSajPXURYqpr+Cu8U9bt8K+XcACIHWqWrvWCKyeFmVQ=
github.com/go-fonts/latin-modern v0.2.0 h1:5/Tv1Ek/QCr20C6ZOz15vw3g7GELYL98KWr8Hgo+3vk=
github.com/go-fonts/liberation v0.2.0 h1:jAkAWJP4S+OsrPLZM4/eC9iW7CtHy+HBXrEwZXWo5VM=
github.com/go-fonts/stix v0.1.0 h1:UlZlgrvvmT/58o573ot7NFw0vZasZ5I6bcIft/oMdgg=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81 h1:6zl3BbBhdnMkpSj2YY30qV3gDcVBGtFgVsV3+/i+mKQ=
github.com/go-pdf/fpdf v0.6.0 h1:MlgtGIfsdMEEQJr2le6b/HNr1ZlQwxyWr77r2aj2U/8=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U=
github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=
github.com/goccy/go-yaml v1.11.0 h1:n7Z+zx8S9f9KgzG6KtQKf+kwqXZlLNR2F6018Dgau54=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY=
github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc=
github.com/google/go-jsonnet v0.20.0 h1:WG4TTSARuV7bSm4PMB4ohjxe33IHT5WVTrJSU33uT4g=
github.com/google/go-jsonnet v0.20.0/go.mod h1:VbgWF9JX7ztlv770x/TolZNGGFfiHEVx9G6ca2eUmeA=
github.com/google/go-pkcs11 v0.3.0 h1:PVRnTgtArZ3QQqTGtbtjtnIkzl2iY2kt24yqbrf7td8=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
github.com/hamba/avro/v2 v2.17.2 h1:6PKpEWzJfNnvBgn7m2/8WYaDOUASxfDU+Jyb4ojDgFY=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hoisie/redis v0.0.0-20160730154456-b5c6e81454e0 h1:mjZV3MTu2A5gwfT5G9IIiLGdwZNciyVq5qqnmJJZ2JI=
github.com/hoisie/redis v0.0.0-20160730154456-b5c6e81454e0/go.mod h1:pMYMxVaKJqCDC1JUg/XbPJ4/fSazB25zORpFzqsIGIc=
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465 h1:KwWnWVWCNtNq/ewIX7HIKnELmEx2nDP42yskD/pi7QE=
github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b h1:ogbOPx86mIhFy764gGkqnkFC8m5PJA7sPzlk9ppLVQA=
github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/itchyny/gojq v0.12.9 h1:biKpbKwMxVYhCU1d6mR7qMr3f0Hn9F5k5YykCVb3gmM=
github.com/itchyny/gojq v0.12.9/go.mod h1:T4Ip7AETUXeGpD+436m+UEl3m3tokRgajd5pRfsR5oE=
github.com/itchyny/timefmt-go v0.1.4 h1:hFEfWVdwsEi+CY8xY2FtgWHGQaBaC3JeHd+cve0ynVM=
github.com/itchyny/timefmt-go v0.1.4/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5 h1:PJr+ZMXIecYc1Ey2zucXdR73SMBtgjPgwa31099IMv0=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4=
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lyft/protoc-gen-star v0.6.1 h1:erE0rdztuaDq3bpGifD95wfoPrSZc95nGA6tbiNYh6M=
github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4 h1:sIXJOMrYnQZJu7OB7ANSF4MYri2fTEGIsRLz6LwI4xE=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/miekg/dns v1.1.33 h1:8KUVEKrUw2dmu1Ys0aWnkEJgoRaLAzNysfCh2KSMWiI=
github.com/miekg/dns v1.1.33/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs=
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mmcloughlin/avo v0.5.0 h1:nAco9/aI9Lg2kiuROBY6BhCI/z0t5jEvJfjWbL8qXLU=
github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/phpdave11/gofpdf v1.4.2 h1:KPKiIbfwbvC/wOncwhrpRdXVj2CZTCFlw4wnoyjtHfQ=
github.com/phpdave11/gofpdi v1.0.13 h1:o61duiW8M9sMlkVXWlvP92sZJtGKENvW3VExs6dZukQ=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A=
github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs=
github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245 h1:K1Xf3bKttbF+koVGaX5xngRIZ5bVjbmPnaxE/dR08uY=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/substrait-io/substrait-go v0.4.2 h1:buDnjsb3qAqTaNbOR7VKmNgXf4lYQxWEcnSGUWBtmN8=
github.com/tidwall/gjson v1.14.2 h1:6BBkirS0rAHjumnjHF6qgy5d2YAJ1TLIaFE2lzfOLqo=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
go.opentelemetry.io/contrib/detectors/gcp v1.27.0/go.mod h1:amd+4uZxqJAUx7zI1JvygUtAc2EVWtQeyz8D+3161SQ=
go.opentelemetry.io/contrib/detectors/gcp v1.28.0/go.mod h1:9BIqH22qyHWAiZxQh0whuJygro59z+nbMVuc7ciiGug=
go.opentelemetry.io/otel v1.23.1/go.mod h1:Td0134eafDLcTS4y+zQ26GE8u3dEuRBiBCTUIRHaikA=
go.opentelemetry.io/otel/bridge/opencensus v0.40.0 h1:pqDiayRhBgoqy1vwnscik+TizcImJ58l053NScJyZso=
go.opentelemetry.io/otel/bridge/opencensus v0.40.0/go.mod h1:1NvVHb6tLTe5A9qCYz+eErW0t8iPn4ZfR6tDKcqlGTM=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 h1:jd0+5t/YynESZqsSyPz+7PAFdEop0dlN0+PkyHYo8oI=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0/go.mod h1:U707O40ee1FpQGyhvqnzmCJm1Wh6OX6GGBVn0E6Uyyk=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 h1:bflGWrfYyuulcdxf14V6n9+CoQcu5SAAdHmDPAJnlps=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0/go.mod h1:qcTO4xHAxZLaLxPd60TdE88rxtItPHgHWqOhOGRr0as=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.44.0/go.mod h1:sTt30Evb7hJB/gEk27qLb1+l9n4Tb8HvHkR0Wx3S6CU=
go.opentelemetry.io/otel/metric v1.23.1/go.mod h1:mpG2QPlAfnK8yNhNJAxDZruU9Y1/HubbC+KyH8FaCWI=
go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A=
go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw=
go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg=
go.opentelemetry.io/otel/trace v1.23.1/go.mod h1:4IpnpJFwr1mo/6HL8XIPJaE9y0+u1KcVmuW7dwFSVrI=
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
golang.org/x/image v0.0.0-20220302094943-723b81ca9867 h1:TcHcE0vrmgzNH1v3ppjcMGbhG5+9fMuvOmUYwNEF4q4=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs=
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk=
golang.org/x/telemetry v0.0.0-20250710130107-8d8967aff50b/go.mod h1:4ZwOYna0/zsOKwuR5X/m0QFOJpSZvAxFfkQT+Erd9D4=
golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488/go.mod h1:fGb/2+tgXXjhjHsTNdVEEMZNWA0quBnfrO+AfoDSAKw=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc=
gonum.org/v1/plot v0.10.1 h1:dnifSs43YJuNMDzB7v8wV64O4ABBHReuAVAoBxqBqS4=
google.golang.org/api v0.174.0/go.mod h1:aC7tB6j0HR1Nl0ni5ghpx6iLasmAX78Zkh/wgxAAjLg=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/genproto v0.0.0-20230725213213-b022f6e96895/go.mod h1:0ggbjUrZYpy1q+ANUS30SEoGZ53cdfwtbuG7Ptgy108=
google.golang.org/genproto v0.0.0-20230731193218-e0aa005b6bdf/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8=
google.golang.org/genproto/googleapis/api v0.0.0-20230725213213-b022f6e96895/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ=
google.golang.org/genproto/googleapis/api v0.0.0-20240515191416-fc5f0ca64291/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g=
google.golang.org/genproto/googleapis/api v0.0.0-20240930140551-af27646dc61f/go.mod h1:CLGoBuH1VHxAUXVPP8FfPwPEVJB6lz3URE5mY2SuayE=
google.golang.org/genproto/googleapis/api v0.0.0-20250227231956-55c901821b1e h1:nsxey/MfoGzYNduN0NN/+hqP9iiCIYsrVbXb/8hjFM8=
google.golang.org/genproto/googleapis/bytestream v0.0.0-20231120223509-83a465c0220f/go.mod h1:iIgEblxoG4klcXsG0d9cpoxJ4xndv6+1FkDROCHhPRI=
google.golang.org/genproto/googleapis/bytestream v0.0.0-20240102182953-50ed04b92917/go.mod h1:O9TvT7A9NLgdqqF0JJXJ+axpaoYiEb8txGmkvy+AvLc=
google.golang.org/genproto/googleapis/bytestream v0.0.0-20240513163218-0867130af1f8/go.mod h1:RCpt0+3mpEDPldc32vXBM8ADXlFL95T8Chxx0nv0/zE=
google.golang.org/genproto/googleapis/bytestream v0.0.0-20250115164207-1a7da9e5054f h1:NtrhicUU5+S4TaE5AurusJUYfAo/QB8a+kbIXipuJeI=
google.golang.org/genproto/googleapis/bytestream v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:35wIojE/F1ptq1nfNDNjtowabHoMSA2qQs7+smpCO5s=
google.golang.org/genproto/googleapis/bytestream v0.0.0-20250603155806-513f23925822 h1:zWFRixYR5QlotL+Uv3YfsPRENIrQFXiGs+iwqel6fOQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230725213213-b022f6e96895/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA=
google.golang.org/grpc/examples v0.0.0-20230224211313-3775f633ce20 h1:MLBCGN1O7GzIx+cBiwfYPwtmZ41U3Mn/cotLJciaArI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
honnef.co/go/tools v0.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o=
lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo=
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/libc v1.22.4 h1:wymSbZb0AlrjdAVX3cjreCHTPCpPARbQXNz6BHPzdwQ=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/sqlite v1.21.2 h1:ixuUG0QS413Vfzyx6FWx6PYTmHaOegTY+hjzhn7L+a0=
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
modernc.org/tcl v1.15.1 h1:mOQwiEK4p7HruMZcwKTZPw/aqtGM4aY00uzWhlKKYws=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE=
rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=

View File

@@ -1,5 +1,41 @@
# Changes
## [0.6.7](https://github.com/googleapis/google-cloud-go/compare/longrunning/v0.6.6...longrunning/v0.6.7) (2025-04-15)
### Bug Fixes
* **longrunning:** Update google.golang.org/api to 0.229.0 ([3319672](https://github.com/googleapis/google-cloud-go/commit/3319672f3dba84a7150772ccb5433e02dab7e201))
## [0.6.6](https://github.com/googleapis/google-cloud-go/compare/longrunning/v0.6.5...longrunning/v0.6.6) (2025-03-13)
### Bug Fixes
* **longrunning:** Update golang.org/x/net to 0.37.0 ([1144978](https://github.com/googleapis/google-cloud-go/commit/11449782c7fb4896bf8b8b9cde8e7441c84fb2fd))
## [0.6.5](https://github.com/googleapis/google-cloud-go/compare/longrunning/v0.6.4...longrunning/v0.6.5) (2025-03-06)
### Bug Fixes
* **longrunning:** Fix out-of-sync version.go ([28f0030](https://github.com/googleapis/google-cloud-go/commit/28f00304ebb13abfd0da2f45b9b79de093cca1ec))
## [0.6.4](https://github.com/googleapis/google-cloud-go/compare/longrunning/v0.6.3...longrunning/v0.6.4) (2025-01-02)
### Bug Fixes
* **longrunning:** Update golang.org/x/net to v0.33.0 ([e9b0b69](https://github.com/googleapis/google-cloud-go/commit/e9b0b69644ea5b276cacff0a707e8a5e87efafc9))
## [0.6.3](https://github.com/googleapis/google-cloud-go/compare/longrunning/v0.6.2...longrunning/v0.6.3) (2024-11-19)
### Documentation
* **longrunning:** Clarity and typo fixes for documentation ([c1e936d](https://github.com/googleapis/google-cloud-go/commit/c1e936df6527933f5e7c31be0f95aa46ff2c0e61))
* **longrunning:** Fix example rpc naming ([c1e936d](https://github.com/googleapis/google-cloud-go/commit/c1e936df6527933f5e7c31be0f95aa46ff2c0e61))
## [0.6.2](https://github.com/googleapis/google-cloud-go/compare/longrunning/v0.6.1...longrunning/v0.6.2) (2024-10-23)

View File

@@ -1,4 +1,4 @@
// Copyright 2024 Google LLC
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ type OperationIterator struct {
InternalFetch func(pageSize int, pageToken string) (results []*longrunningpb.Operation, nextPageToken string, err error)
}
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
// PageInfo supports pagination. See the [google.golang.org/api/iterator] package for details.
func (it *OperationIterator) PageInfo() *iterator.PageInfo {
return it.pageInfo
}

View File

@@ -1,4 +1,4 @@
// Copyright 2024 Google LLC
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
// Copyright 2024 Google LLC
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
//
// To get started with this package, create a client.
//
// // go get cloud.google.com/go/longrunning/autogen@latest
// ctx := context.Background()
// // This snippet has been automatically generated and should be regarded as a code template only.
// // It will require modifications to work:
@@ -51,19 +52,7 @@
//
// # Using the Client
//
// The following is an example of making an API call with the newly created client.
//
// ctx := context.Background()
// // This snippet has been automatically generated and should be regarded as a code template only.
// // It will require modifications to work:
// // - It may require correct/in-range values for request initialization.
// // - It may require specifying regional endpoints when creating the service client as shown in:
// // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options
// c, err := longrunning.NewOperationsClient(ctx)
// if err != nil {
// // TODO: Handle error.
// }
// defer c.Close()
// The following is an example of making an API call with the newly created client, mentioned above.
//
// req := &longrunningpb.CancelOperationRequest{
// // TODO: Fill request struct fields.
@@ -88,30 +77,3 @@
// [Debugging Client Libraries]: https://pkg.go.dev/cloud.google.com/go#hdr-Debugging
// [Inspecting errors]: https://pkg.go.dev/cloud.google.com/go#hdr-Inspecting_errors
package longrunning // import "cloud.google.com/go/longrunning/autogen"
import (
"context"
"google.golang.org/api/option"
)
// For more information on implementing a client constructor hook, see
// https://github.com/googleapis/google-cloud-go/wiki/Customizing-constructors.
type clientHookParams struct{}
type clientHook func(context.Context, clientHookParams) ([]option.ClientOption, error)
var versionClient string
func getVersionClient() string {
if versionClient == "" {
return "UNKNOWN"
}
return versionClient
}
// DefaultAuthScopes reports the default set of authentication scopes to use with this package.
func DefaultAuthScopes() []string {
return []string{
"",
}
}

View File

@@ -0,0 +1,99 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by protoc-gen-go_gapic. DO NOT EDIT.
package longrunning
import (
"context"
"io"
"log/slog"
"net/http"
"github.com/googleapis/gax-go/v2/internallog"
"github.com/googleapis/gax-go/v2/internallog/grpclog"
"google.golang.org/api/googleapi"
"google.golang.org/api/option"
"google.golang.org/grpc"
"google.golang.org/protobuf/proto"
)
const serviceName = "longrunning.googleapis.com"
// For more information on implementing a client constructor hook, see
// https://github.com/googleapis/google-cloud-go/wiki/Customizing-constructors.
type clientHookParams struct{}
type clientHook func(context.Context, clientHookParams) ([]option.ClientOption, error)
var versionClient string
func getVersionClient() string {
if versionClient == "" {
return "UNKNOWN"
}
return versionClient
}
// DefaultAuthScopes reports the default set of authentication scopes to use with this package.
func DefaultAuthScopes() []string {
return []string{}
}
func executeHTTPRequestWithResponse(ctx context.Context, client *http.Client, req *http.Request, logger *slog.Logger, body []byte, rpc string) ([]byte, *http.Response, error) {
logger.DebugContext(ctx, "api request", "serviceName", serviceName, "rpcName", rpc, "request", internallog.HTTPRequest(req, body))
resp, err := client.Do(req)
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()
buf, err := io.ReadAll(resp.Body)
if err != nil {
return nil, nil, err
}
logger.DebugContext(ctx, "api response", "serviceName", serviceName, "rpcName", rpc, "response", internallog.HTTPResponse(resp, buf))
if err = googleapi.CheckResponseWithBody(resp, buf); err != nil {
return nil, nil, err
}
return buf, resp, nil
}
func executeHTTPRequest(ctx context.Context, client *http.Client, req *http.Request, logger *slog.Logger, body []byte, rpc string) ([]byte, error) {
buf, _, err := executeHTTPRequestWithResponse(ctx, client, req, logger, body, rpc)
return buf, err
}
func executeStreamingHTTPRequest(ctx context.Context, client *http.Client, req *http.Request, logger *slog.Logger, body []byte, rpc string) (*http.Response, error) {
logger.DebugContext(ctx, "api request", "serviceName", serviceName, "rpcName", rpc, "request", internallog.HTTPRequest(req, body))
resp, err := client.Do(req)
if err != nil {
return nil, err
}
logger.DebugContext(ctx, "api response", "serviceName", serviceName, "rpcName", rpc, "response", internallog.HTTPResponse(resp, nil))
if err = googleapi.CheckResponse(resp); err != nil {
return nil, err
}
return resp, nil
}
func executeRPC[I proto.Message, O proto.Message](ctx context.Context, fn func(context.Context, I, ...grpc.CallOption) (O, error), req I, opts []grpc.CallOption, logger *slog.Logger, rpc string) (O, error) {
var zero O
logger.DebugContext(ctx, "api request", "serviceName", serviceName, "rpcName", rpc, "request", grpclog.ProtoMessageRequest(ctx, req))
resp, err := fn(ctx, req, opts...)
if err != nil {
return zero, err
}
logger.DebugContext(ctx, "api response", "serviceName", serviceName, "rpcName", rpc, "response", grpclog.ProtoMessageResponse(resp))
return resp, err
}

View File

@@ -1,4 +1,4 @@
// Copyright 2024 Google LLC
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.2
// protoc-gen-go v1.35.2
// protoc v4.25.3
// source: google/longrunning/operations.proto
@@ -67,7 +67,8 @@ type Operation struct {
Done bool `protobuf:"varint,3,opt,name=done,proto3" json:"done,omitempty"`
// The operation result, which can be either an `error` or a valid `response`.
// If `done` == `false`, neither `error` nor `response` is set.
// If `done` == `true`, exactly one of `error` or `response` is set.
// If `done` == `true`, exactly one of `error` or `response` can be set.
// Some services might not provide the result.
//
// Types that are assignable to Result:
//
@@ -78,11 +79,9 @@ type Operation struct {
func (x *Operation) Reset() {
*x = Operation{}
if protoimpl.UnsafeEnabled {
mi := &file_google_longrunning_operations_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_google_longrunning_operations_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Operation) String() string {
@@ -93,7 +92,7 @@ func (*Operation) ProtoMessage() {}
func (x *Operation) ProtoReflect() protoreflect.Message {
mi := &file_google_longrunning_operations_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -160,7 +159,7 @@ type Operation_Error struct {
}
type Operation_Response struct {
// The normal response of the operation in case of success. If the original
// The normal, successful response of the operation. If the original
// method returns no data on success, such as `Delete`, the response is
// `google.protobuf.Empty`. If the original method is standard
// `Get`/`Create`/`Update`, the response should be the resource. For other
@@ -175,7 +174,8 @@ func (*Operation_Error) isOperation_Result() {}
func (*Operation_Response) isOperation_Result() {}
// The request message for [Operations.GetOperation][google.longrunning.Operations.GetOperation].
// The request message for
// [Operations.GetOperation][google.longrunning.Operations.GetOperation].
type GetOperationRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -187,11 +187,9 @@ type GetOperationRequest struct {
func (x *GetOperationRequest) Reset() {
*x = GetOperationRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_google_longrunning_operations_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_google_longrunning_operations_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetOperationRequest) String() string {
@@ -202,7 +200,7 @@ func (*GetOperationRequest) ProtoMessage() {}
func (x *GetOperationRequest) ProtoReflect() protoreflect.Message {
mi := &file_google_longrunning_operations_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -224,7 +222,8 @@ func (x *GetOperationRequest) GetName() string {
return ""
}
// The request message for [Operations.ListOperations][google.longrunning.Operations.ListOperations].
// The request message for
// [Operations.ListOperations][google.longrunning.Operations.ListOperations].
type ListOperationsRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -242,11 +241,9 @@ type ListOperationsRequest struct {
func (x *ListOperationsRequest) Reset() {
*x = ListOperationsRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_google_longrunning_operations_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_google_longrunning_operations_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListOperationsRequest) String() string {
@@ -257,7 +254,7 @@ func (*ListOperationsRequest) ProtoMessage() {}
func (x *ListOperationsRequest) ProtoReflect() protoreflect.Message {
mi := &file_google_longrunning_operations_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -300,7 +297,8 @@ func (x *ListOperationsRequest) GetPageToken() string {
return ""
}
// The response message for [Operations.ListOperations][google.longrunning.Operations.ListOperations].
// The response message for
// [Operations.ListOperations][google.longrunning.Operations.ListOperations].
type ListOperationsResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -314,11 +312,9 @@ type ListOperationsResponse struct {
func (x *ListOperationsResponse) Reset() {
*x = ListOperationsResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_google_longrunning_operations_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_google_longrunning_operations_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListOperationsResponse) String() string {
@@ -329,7 +325,7 @@ func (*ListOperationsResponse) ProtoMessage() {}
func (x *ListOperationsResponse) ProtoReflect() protoreflect.Message {
mi := &file_google_longrunning_operations_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -358,7 +354,8 @@ func (x *ListOperationsResponse) GetNextPageToken() string {
return ""
}
// The request message for [Operations.CancelOperation][google.longrunning.Operations.CancelOperation].
// The request message for
// [Operations.CancelOperation][google.longrunning.Operations.CancelOperation].
type CancelOperationRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -370,11 +367,9 @@ type CancelOperationRequest struct {
func (x *CancelOperationRequest) Reset() {
*x = CancelOperationRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_google_longrunning_operations_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_google_longrunning_operations_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CancelOperationRequest) String() string {
@@ -385,7 +380,7 @@ func (*CancelOperationRequest) ProtoMessage() {}
func (x *CancelOperationRequest) ProtoReflect() protoreflect.Message {
mi := &file_google_longrunning_operations_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -407,7 +402,8 @@ func (x *CancelOperationRequest) GetName() string {
return ""
}
// The request message for [Operations.DeleteOperation][google.longrunning.Operations.DeleteOperation].
// The request message for
// [Operations.DeleteOperation][google.longrunning.Operations.DeleteOperation].
type DeleteOperationRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -419,11 +415,9 @@ type DeleteOperationRequest struct {
func (x *DeleteOperationRequest) Reset() {
*x = DeleteOperationRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_google_longrunning_operations_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_google_longrunning_operations_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeleteOperationRequest) String() string {
@@ -434,7 +428,7 @@ func (*DeleteOperationRequest) ProtoMessage() {}
func (x *DeleteOperationRequest) ProtoReflect() protoreflect.Message {
mi := &file_google_longrunning_operations_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -456,7 +450,8 @@ func (x *DeleteOperationRequest) GetName() string {
return ""
}
// The request message for [Operations.WaitOperation][google.longrunning.Operations.WaitOperation].
// The request message for
// [Operations.WaitOperation][google.longrunning.Operations.WaitOperation].
type WaitOperationRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -472,11 +467,9 @@ type WaitOperationRequest struct {
func (x *WaitOperationRequest) Reset() {
*x = WaitOperationRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_google_longrunning_operations_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_google_longrunning_operations_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *WaitOperationRequest) String() string {
@@ -487,7 +480,7 @@ func (*WaitOperationRequest) ProtoMessage() {}
func (x *WaitOperationRequest) ProtoReflect() protoreflect.Message {
mi := &file_google_longrunning_operations_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -520,11 +513,10 @@ func (x *WaitOperationRequest) GetTimeout() *durationpb.Duration {
//
// Example:
//
// rpc LongRunningRecognize(LongRunningRecognizeRequest)
// returns (google.longrunning.Operation) {
// rpc Export(ExportRequest) returns (google.longrunning.Operation) {
// option (google.longrunning.operation_info) = {
// response_type: "LongRunningRecognizeResponse"
// metadata_type: "LongRunningRecognizeMetadata"
// response_type: "ExportResponse"
// metadata_type: "ExportMetadata"
// };
// }
type OperationInfo struct {
@@ -553,11 +545,9 @@ type OperationInfo struct {
func (x *OperationInfo) Reset() {
*x = OperationInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_google_longrunning_operations_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_google_longrunning_operations_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *OperationInfo) String() string {
@@ -568,7 +558,7 @@ func (*OperationInfo) ProtoMessage() {}
func (x *OperationInfo) ProtoReflect() protoreflect.Message {
mi := &file_google_longrunning_operations_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -632,14 +622,14 @@ var file_google_longrunning_operations_proto_rawDesc = []byte{
0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70,
0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2f, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72,
0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73,
0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64,
0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65,
0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0xcf, 0x01, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
@@ -739,17 +729,18 @@ var file_google_longrunning_operations_proto_rawDesc = []byte{
0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6c, 0x6f, 0x6e, 0x67, 0x72, 0x75,
0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49,
0x6e, 0x66, 0x6f, 0x52, 0x0d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e,
0x66, 0x6f, 0x42, 0x9d, 0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x66, 0x6f, 0x42, 0xa5, 0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x6c, 0x6f, 0x6e, 0x67, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x42, 0x0f, 0x4f,
0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01,
0x5a, 0x43, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x2f, 0x6c, 0x6f, 0x6e, 0x67, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e,
0x67, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x67, 0x65, 0x6e, 0x2f, 0x6c, 0x6f, 0x6e, 0x67, 0x72, 0x75,
0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x70, 0x62, 0x3b, 0x6c, 0x6f, 0x6e, 0x67, 0x72, 0x75, 0x6e, 0x6e,
0x69, 0x6e, 0x67, 0x70, 0x62, 0xf8, 0x01, 0x01, 0xaa, 0x02, 0x12, 0x47, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x4c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0xca, 0x02, 0x12,
0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5c, 0x4c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69,
0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x69, 0x6e, 0x67, 0x70, 0x62, 0xf8, 0x01, 0x01, 0xa2, 0x02, 0x05, 0x47, 0x4c, 0x52, 0x55, 0x4e,
0xaa, 0x02, 0x12, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x4c, 0x6f, 0x6e, 0x67, 0x52, 0x75,
0x6e, 0x6e, 0x69, 0x6e, 0x67, 0xca, 0x02, 0x12, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5c, 0x4c,
0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
@@ -810,104 +801,6 @@ func file_google_longrunning_operations_proto_init() {
if File_google_longrunning_operations_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_google_longrunning_operations_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Operation); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_google_longrunning_operations_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*GetOperationRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_google_longrunning_operations_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*ListOperationsRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_google_longrunning_operations_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*ListOperationsResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_google_longrunning_operations_proto_msgTypes[4].Exporter = func(v any, i int) any {
switch v := v.(*CancelOperationRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_google_longrunning_operations_proto_msgTypes[5].Exporter = func(v any, i int) any {
switch v := v.(*DeleteOperationRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_google_longrunning_operations_proto_msgTypes[6].Exporter = func(v any, i int) any {
switch v := v.(*WaitOperationRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_google_longrunning_operations_proto_msgTypes[7].Exporter = func(v any, i int) any {
switch v := v.(*OperationInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_google_longrunning_operations_proto_msgTypes[0].OneofWrappers = []any{
(*Operation_Error)(nil),
(*Operation_Response)(nil),
@@ -947,14 +840,6 @@ const _ = grpc.SupportPackageIsVersion6
type OperationsClient interface {
// Lists operations that match the specified filter in the request. If the
// server doesn't support this method, it returns `UNIMPLEMENTED`.
//
// NOTE: the `name` binding allows API services to override the binding
// to use different resource name schemes, such as `users/*/operations`. To
// override the binding, API services can add a binding such as
// `"/v1/{name=users/*}/operations"` to their service configuration.
// For backwards compatibility, the default name includes the operations
// collection id, however overriding users must ensure the name binding
// is the parent resource, without the operations collection id.
ListOperations(ctx context.Context, in *ListOperationsRequest, opts ...grpc.CallOption) (*ListOperationsResponse, error)
// Gets the latest state of a long-running operation. Clients can use this
// method to poll the operation result at intervals as recommended by the API
@@ -973,8 +858,9 @@ type OperationsClient interface {
// other methods to check whether the cancellation succeeded or whether the
// operation completed despite cancellation. On successful cancellation,
// the operation is not deleted; instead, it becomes an operation with
// an [Operation.error][google.longrunning.Operation.error] value with a [google.rpc.Status.code][google.rpc.Status.code] of 1,
// corresponding to `Code.CANCELLED`.
// an [Operation.error][google.longrunning.Operation.error] value with a
// [google.rpc.Status.code][google.rpc.Status.code] of `1`, corresponding to
// `Code.CANCELLED`.
CancelOperation(ctx context.Context, in *CancelOperationRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
// Waits until the specified long-running operation is done or reaches at most
// a specified timeout, returning the latest state. If the operation is
@@ -1045,14 +931,6 @@ func (c *operationsClient) WaitOperation(ctx context.Context, in *WaitOperationR
type OperationsServer interface {
// Lists operations that match the specified filter in the request. If the
// server doesn't support this method, it returns `UNIMPLEMENTED`.
//
// NOTE: the `name` binding allows API services to override the binding
// to use different resource name schemes, such as `users/*/operations`. To
// override the binding, API services can add a binding such as
// `"/v1/{name=users/*}/operations"` to their service configuration.
// For backwards compatibility, the default name includes the operations
// collection id, however overriding users must ensure the name binding
// is the parent resource, without the operations collection id.
ListOperations(context.Context, *ListOperationsRequest) (*ListOperationsResponse, error)
// Gets the latest state of a long-running operation. Clients can use this
// method to poll the operation result at intervals as recommended by the API
@@ -1071,8 +949,9 @@ type OperationsServer interface {
// other methods to check whether the cancellation succeeded or whether the
// operation completed despite cancellation. On successful cancellation,
// the operation is not deleted; instead, it becomes an operation with
// an [Operation.error][google.longrunning.Operation.error] value with a [google.rpc.Status.code][google.rpc.Status.code] of 1,
// corresponding to `Code.CANCELLED`.
// an [Operation.error][google.longrunning.Operation.error] value with a
// [google.rpc.Status.code][google.rpc.Status.code] of `1`, corresponding to
// `Code.CANCELLED`.
CancelOperation(context.Context, *CancelOperationRequest) (*emptypb.Empty, error)
// Waits until the specified long-running operation is done or reaches at most
// a specified timeout, returning the latest state. If the operation is

View File

@@ -1,4 +1,4 @@
// Copyright 2024 Google LLC
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ import (
"bytes"
"context"
"fmt"
"io"
"log/slog"
"math"
"net/http"
"net/url"
@@ -28,7 +28,6 @@ import (
longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb"
gax "github.com/googleapis/gax-go/v2"
"google.golang.org/api/googleapi"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
"google.golang.org/api/option/internaloption"
@@ -188,12 +187,12 @@ type internalOperationsClient interface {
// Manages long-running operations with an API service.
//
// When an API method normally takes long time to complete, it can be designed
// to return Operation to the client, and the client can use this
// interface to receive the real response asynchronously by polling the
// operation resource, or pass the operation resource to another API (such as
// Google Cloud Pub/Sub API) to receive the response. Any API service that
// returns long-running operations should implement the Operations interface
// so developers can have a consistent client experience.
// to return Operation to the client, and the
// client can use this interface to receive the real response asynchronously by
// polling the operation resource, or pass the operation resource to another API
// (such as Pub/Sub API) to receive the response. Any API service that returns
// long-running operations should implement the Operations interface so
// developers can have a consistent client experience.
type OperationsClient struct {
// The internal transport-dependent client.
internalClient internalOperationsClient
@@ -227,14 +226,6 @@ func (c *OperationsClient) Connection() *grpc.ClientConn {
// ListOperations lists operations that match the specified filter in the request. If the
// server doesnt support this method, it returns UNIMPLEMENTED.
//
// NOTE: the name binding allows API services to override the binding
// to use different resource name schemes, such as users/*/operations. To
// override the binding, API services can add a binding such as
// "/v1/{name=users/*}/operations" to their service configuration.
// For backwards compatibility, the default name includes the operations
// collection id, however overriding users must ensure the name binding
// is the parent resource, without the operations collection id.
func (c *OperationsClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator {
return c.internalClient.ListOperations(ctx, req, opts...)
}
@@ -262,8 +253,9 @@ func (c *OperationsClient) DeleteOperation(ctx context.Context, req *longrunning
// other methods to check whether the cancellation succeeded or whether the
// operation completed despite cancellation. On successful cancellation,
// the operation is not deleted; instead, it becomes an operation with
// an Operation.error value with a google.rpc.Status.code of 1,
// corresponding to Code.CANCELLED.
// an Operation.error value with a
// google.rpc.Status.code of 1, corresponding to
// Code.CANCELLED.
func (c *OperationsClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error {
return c.internalClient.CancelOperation(ctx, req, opts...)
}
@@ -296,6 +288,8 @@ type operationsGRPCClient struct {
// The x-goog-* metadata to be sent with each request.
xGoogHeaders []string
logger *slog.Logger
}
// NewOperationsClient creates a new operations client based on gRPC.
@@ -304,12 +298,12 @@ type operationsGRPCClient struct {
// Manages long-running operations with an API service.
//
// When an API method normally takes long time to complete, it can be designed
// to return Operation to the client, and the client can use this
// interface to receive the real response asynchronously by polling the
// operation resource, or pass the operation resource to another API (such as
// Google Cloud Pub/Sub API) to receive the response. Any API service that
// returns long-running operations should implement the Operations interface
// so developers can have a consistent client experience.
// to return Operation to the client, and the
// client can use this interface to receive the real response asynchronously by
// polling the operation resource, or pass the operation resource to another API
// (such as Pub/Sub API) to receive the response. Any API service that returns
// long-running operations should implement the Operations interface so
// developers can have a consistent client experience.
func NewOperationsClient(ctx context.Context, opts ...option.ClientOption) (*OperationsClient, error) {
clientOpts := defaultOperationsGRPCClientOptions()
if newOperationsClientHook != nil {
@@ -330,6 +324,7 @@ func NewOperationsClient(ctx context.Context, opts ...option.ClientOption) (*Ope
connPool: connPool,
operationsClient: longrunningpb.NewOperationsClient(connPool),
CallOptions: &client.CallOptions,
logger: internaloption.GetLogger(opts),
}
c.setGoogleClientInfo()
@@ -376,6 +371,8 @@ type operationsRESTClient struct {
// Points back to the CallOptions field of the containing OperationsClient
CallOptions **OperationsCallOptions
logger *slog.Logger
}
// NewOperationsRESTClient creates a new operations rest client.
@@ -383,12 +380,12 @@ type operationsRESTClient struct {
// Manages long-running operations with an API service.
//
// When an API method normally takes long time to complete, it can be designed
// to return Operation to the client, and the client can use this
// interface to receive the real response asynchronously by polling the
// operation resource, or pass the operation resource to another API (such as
// Google Cloud Pub/Sub API) to receive the response. Any API service that
// returns long-running operations should implement the Operations interface
// so developers can have a consistent client experience.
// to return Operation to the client, and the
// client can use this interface to receive the real response asynchronously by
// polling the operation resource, or pass the operation resource to another API
// (such as Pub/Sub API) to receive the response. Any API service that returns
// long-running operations should implement the Operations interface so
// developers can have a consistent client experience.
func NewOperationsRESTClient(ctx context.Context, opts ...option.ClientOption) (*OperationsClient, error) {
clientOpts := append(defaultOperationsRESTClientOptions(), opts...)
httpClient, endpoint, err := httptransport.NewClient(ctx, clientOpts...)
@@ -401,6 +398,7 @@ func NewOperationsRESTClient(ctx context.Context, opts ...option.ClientOption) (
endpoint: endpoint,
httpClient: httpClient,
CallOptions: &callOpts,
logger: internaloption.GetLogger(opts),
}
c.setGoogleClientInfo()
@@ -464,7 +462,7 @@ func (c *operationsGRPCClient) ListOperations(ctx context.Context, req *longrunn
}
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.operationsClient.ListOperations(ctx, req, settings.GRPC...)
resp, err = executeRPC(ctx, c.operationsClient.ListOperations, req, settings.GRPC, c.logger, "ListOperations")
return err
}, opts...)
if err != nil {
@@ -499,7 +497,7 @@ func (c *operationsGRPCClient) GetOperation(ctx context.Context, req *longrunnin
var resp *longrunningpb.Operation
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.operationsClient.GetOperation(ctx, req, settings.GRPC...)
resp, err = executeRPC(ctx, c.operationsClient.GetOperation, req, settings.GRPC, c.logger, "GetOperation")
return err
}, opts...)
if err != nil {
@@ -516,7 +514,7 @@ func (c *operationsGRPCClient) DeleteOperation(ctx context.Context, req *longrun
opts = append((*c.CallOptions).DeleteOperation[0:len((*c.CallOptions).DeleteOperation):len((*c.CallOptions).DeleteOperation)], opts...)
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
_, err = c.operationsClient.DeleteOperation(ctx, req, settings.GRPC...)
_, err = executeRPC(ctx, c.operationsClient.DeleteOperation, req, settings.GRPC, c.logger, "DeleteOperation")
return err
}, opts...)
return err
@@ -530,7 +528,7 @@ func (c *operationsGRPCClient) CancelOperation(ctx context.Context, req *longrun
opts = append((*c.CallOptions).CancelOperation[0:len((*c.CallOptions).CancelOperation):len((*c.CallOptions).CancelOperation)], opts...)
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
_, err = c.operationsClient.CancelOperation(ctx, req, settings.GRPC...)
_, err = executeRPC(ctx, c.operationsClient.CancelOperation, req, settings.GRPC, c.logger, "CancelOperation")
return err
}, opts...)
return err
@@ -542,7 +540,7 @@ func (c *operationsGRPCClient) WaitOperation(ctx context.Context, req *longrunni
var resp *longrunningpb.Operation
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.operationsClient.WaitOperation(ctx, req, settings.GRPC...)
resp, err = executeRPC(ctx, c.operationsClient.WaitOperation, req, settings.GRPC, c.logger, "WaitOperation")
return err
}, opts...)
if err != nil {
@@ -553,14 +551,6 @@ func (c *operationsGRPCClient) WaitOperation(ctx context.Context, req *longrunni
// ListOperations lists operations that match the specified filter in the request. If the
// server doesnt support this method, it returns UNIMPLEMENTED.
//
// NOTE: the name binding allows API services to override the binding
// to use different resource name schemes, such as users/*/operations. To
// override the binding, API services can add a binding such as
// "/v1/{name=users/*}/operations" to their service configuration.
// For backwards compatibility, the default name includes the operations
// collection id, however overriding users must ensure the name binding
// is the parent resource, without the operations collection id.
func (c *operationsRESTClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator {
it := &OperationIterator{}
req = proto.Clone(req).(*longrunningpb.ListOperationsRequest)
@@ -607,21 +597,10 @@ func (c *operationsRESTClient) ListOperations(ctx context.Context, req *longrunn
}
httpReq.Header = headers
httpRsp, err := c.httpClient.Do(httpReq)
buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListOperations")
if err != nil {
return err
}
defer httpRsp.Body.Close()
if err = googleapi.CheckResponse(httpRsp); err != nil {
return err
}
buf, err := io.ReadAll(httpRsp.Body)
if err != nil {
return err
}
if err := unm.Unmarshal(buf, resp); err != nil {
return err
}
@@ -681,17 +660,7 @@ func (c *operationsRESTClient) GetOperation(ctx context.Context, req *longrunnin
httpReq = httpReq.WithContext(ctx)
httpReq.Header = headers
httpRsp, err := c.httpClient.Do(httpReq)
if err != nil {
return err
}
defer httpRsp.Body.Close()
if err = googleapi.CheckResponse(httpRsp); err != nil {
return err
}
buf, err := io.ReadAll(httpRsp.Body)
buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetOperation")
if err != nil {
return err
}
@@ -736,15 +705,8 @@ func (c *operationsRESTClient) DeleteOperation(ctx context.Context, req *longrun
httpReq = httpReq.WithContext(ctx)
httpReq.Header = headers
httpRsp, err := c.httpClient.Do(httpReq)
if err != nil {
return err
}
defer httpRsp.Body.Close()
// Returns nil if there is no error, otherwise wraps
// the response code and body into a non-nil error
return googleapi.CheckResponse(httpRsp)
_, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "DeleteOperation")
return err
}, opts...)
}
@@ -756,8 +718,9 @@ func (c *operationsRESTClient) DeleteOperation(ctx context.Context, req *longrun
// other methods to check whether the cancellation succeeded or whether the
// operation completed despite cancellation. On successful cancellation,
// the operation is not deleted; instead, it becomes an operation with
// an Operation.error value with a google.rpc.Status.code of 1,
// corresponding to Code.CANCELLED.
// an Operation.error value with a
// google.rpc.Status.code of 1, corresponding to
// Code.CANCELLED.
func (c *operationsRESTClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error {
m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true}
jsonReq, err := m.Marshal(req)
@@ -788,15 +751,8 @@ func (c *operationsRESTClient) CancelOperation(ctx context.Context, req *longrun
httpReq = httpReq.WithContext(ctx)
httpReq.Header = headers
httpRsp, err := c.httpClient.Do(httpReq)
if err != nil {
return err
}
defer httpRsp.Body.Close()
// Returns nil if there is no error, otherwise wraps
// the response code and body into a non-nil error
return googleapi.CheckResponse(httpRsp)
_, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "CancelOperation")
return err
}, opts...)
}
@@ -847,17 +803,7 @@ func (c *operationsRESTClient) WaitOperation(ctx context.Context, req *longrunni
httpReq = httpReq.WithContext(ctx)
httpReq.Header = headers
httpRsp, err := c.httpClient.Do(httpReq)
if err != nil {
return err
}
defer httpRsp.Body.Close()
if err = googleapi.CheckResponse(httpRsp); err != nil {
return err
}
buf, err := io.ReadAll(httpRsp.Body)
buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "WaitOperation")
if err != nil {
return err
}

View File

@@ -14,6 +14,11 @@
"bigquery": {
"component": "bigquery"
},
"bigquery/v2": {
"component": "bigquery/v2",
"prerelease": true,
"prerelease-type": "alpha"
},
"bigtable": {
"component": "bigtable"
},
@@ -35,6 +40,9 @@
"pubsub": {
"component": "pubsub"
},
"pubsub/v2": {
"component": "pubsub/v2"
},
"pubsublite": {
"component": "pubsublite"
},

View File

@@ -12,6 +12,12 @@
"advisorynotifications": {
"component": "advisorynotifications"
},
"ai": {
"component": "ai"
},
"aiplatform": {
"component": "aiplatform"
},
"alloydb": {
"component": "alloydb"
},
@@ -84,6 +90,9 @@
"chat": {
"component": "chat"
},
"chronicle": {
"component": "chronicle"
},
"cloudbuild": {
"component": "cloudbuild"
},
@@ -117,6 +126,9 @@
"config": {
"component": "config"
},
"configdelivery": {
"component": "configdelivery"
},
"contactcenterinsights": {
"component": "contactcenterinsights"
},
@@ -159,6 +171,9 @@
"developerconnect": {
"component": "developerconnect"
},
"devicestreaming": {
"component": "devicestreaming"
},
"dialogflow": {
"component": "dialogflow"
},
@@ -189,6 +204,9 @@
"filestore": {
"component": "filestore"
},
"financialservices": {
"component": "financialservices"
},
"functions": {
"component": "functions"
},
@@ -231,12 +249,21 @@
"language": {
"component": "language"
},
"licensemanager": {
"component": "licensemanager"
},
"lifesciences": {
"component": "lifesciences"
},
"longrunning": {
"component": "longrunning"
},
"lustre": {
"component": "lustre"
},
"maintenance": {
"component": "maintenance"
},
"managedidentities": {
"component": "managedidentities"
},
@@ -252,12 +279,18 @@
"memcache": {
"component": "memcache"
},
"memorystore": {
"component": "memorystore"
},
"metastore": {
"component": "metastore"
},
"migrationcenter": {
"component": "migrationcenter"
},
"modelarmor": {
"component": "modelarmor"
},
"monitoring": {
"component": "monitoring"
},
@@ -300,6 +333,9 @@
"parallelstore": {
"component": "parallelstore"
},
"parametermanager": {
"component": "parametermanager"
},
"phishingprotection": {
"component": "phishingprotection"
},
@@ -333,9 +369,6 @@
"resourcemanager": {
"component": "resourcemanager"
},
"resourcesettings": {
"component": "resourcesettings"
},
"retail": {
"component": "retail"
},
@@ -384,9 +417,15 @@
"shopping": {
"component": "shopping"
},
"spanner/benchmarks": {
"component": "spanner/benchmarks"
},
"speech": {
"component": "speech"
},
"storagebatchoperations": {
"component": "storagebatchoperations"
},
"storageinsights": {
"component": "storageinsights"
},

View File

@@ -1,5 +1,38 @@
# Release History
## 1.18.2 (2025-07-31)
### Bugs Fixed
* Fixed a case in which `BearerTokenPolicy` didn't ensure an authentication error is non-retriable
## 1.18.1 (2025-07-10)
### Bugs Fixed
* Fixed incorrect request/response logging try info when logging a request that's being retried.
* Fixed a data race in `ResourceID.String()`
## 1.18.0 (2025-04-03)
### Features Added
* Added `AccessToken.RefreshOn` and updated `BearerTokenPolicy` to consider nonzero values of it when deciding whether to request a new token
## 1.17.1 (2025-03-20)
### Other Changes
* Upgraded to Go 1.23
* Upgraded dependencies
## 1.17.0 (2025-01-07)
### Features Added
* Added field `OperationLocationResultPath` to `runtime.NewPollerOptions[T]` for LROs that use the `Operation-Location` pattern.
* Support `encoding.TextMarshaler` and `encoding.TextUnmarshaler` interfaces in `arm.ResourceID`.
## 1.16.0 (2024-10-17)
### Features Added

View File

@@ -27,3 +27,5 @@ extends:
template: /eng/pipelines/templates/jobs/archetype-sdk-client.yml
parameters:
ServiceDirectory: azcore
TriggeringPaths:
- /eng/

View File

@@ -47,8 +47,13 @@ func HasStatusCode(resp *http.Response, statusCodes ...int) bool {
// AccessToken represents an Azure service bearer access token with expiry information.
// Exported as azcore.AccessToken.
type AccessToken struct {
Token string
// Token is the access token
Token string
// ExpiresOn indicates when the token expires
ExpiresOn time.Time
// RefreshOn is a suggested time to refresh the token.
// Clients should ignore this value when it's zero.
RefreshOn time.Time
}
// TokenRequestOptions contain specific parameter that may be used by credentials types when attempting to get a token.

View File

@@ -71,7 +71,8 @@ func (ov opValues) get(value any) bool {
// NewRequestFromRequest creates a new policy.Request with an existing *http.Request
// Exported as runtime.NewRequestFromRequest().
func NewRequestFromRequest(req *http.Request) (*Request, error) {
policyReq := &Request{req: req}
// populate values so that the same instance is propagated across policies
policyReq := &Request{req: req, values: opValues{}}
if req.Body != nil {
// we can avoid a body copy here if the underlying stream is already a
@@ -117,7 +118,8 @@ func NewRequest(ctx context.Context, httpMethod string, endpoint string) (*Reque
if !(req.URL.Scheme == "http" || req.URL.Scheme == "https") {
return nil, fmt.Errorf("unsupported protocol scheme %s", req.URL.Scheme)
}
return &Request{req: req}, nil
// populate values so that the same instance is propagated across policies
return &Request{req: req, values: opValues{}}, nil
}
// Body returns the original body specified when the Request was created.

View File

@@ -40,12 +40,13 @@ type Poller[T any] struct {
OrigURL string `json:"origURL"`
Method string `json:"method"`
FinalState pollers.FinalStateVia `json:"finalState"`
ResultPath string `json:"resultPath"`
CurState string `json:"state"`
}
// New creates a new Poller from the provided initial response.
// Pass nil for response to create an empty Poller for rehydration.
func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.FinalStateVia) (*Poller[T], error) {
func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.FinalStateVia, resultPath string) (*Poller[T], error) {
if resp == nil {
log.Write(log.EventLRO, "Resuming Operation-Location poller.")
return &Poller[T]{pl: pl}, nil
@@ -82,6 +83,7 @@ func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.Fi
OrigURL: resp.Request.URL.String(),
Method: resp.Request.Method,
FinalState: finalState,
ResultPath: resultPath,
CurState: curState,
}, nil
}
@@ -116,10 +118,6 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error {
var req *exported.Request
var err error
// when the payload is included with the status monitor on
// terminal success it's in the "result" JSON property
payloadPath := "result"
if p.FinalState == pollers.FinalStateViaLocation && p.LocURL != "" {
req, err = exported.NewRequest(ctx, http.MethodGet, p.LocURL)
} else if rl, rlErr := poller.GetResourceLocation(p.resp); rlErr != nil && !errors.Is(rlErr, poller.ErrNoBody) {
@@ -138,7 +136,7 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error {
// if a final GET request has been created, execute it
if req != nil {
// no JSON path when making a final GET request
payloadPath = ""
p.ResultPath = ""
resp, err := p.pl.Do(req)
if err != nil {
return err
@@ -146,5 +144,5 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error {
p.resp = resp
}
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), payloadPath, out)
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), p.ResultPath, out)
}

View File

@@ -40,5 +40,5 @@ const (
Module = "azcore"
// Version is the semantic version (see http://semver.org) of this module.
Version = "v1.16.0"
Version = "v1.18.2"
)

View File

@@ -103,7 +103,7 @@ type RetryOptions struct {
// RetryDelay specifies the initial amount of delay to use before retrying an operation.
// The value is used only if the HTTP response does not contain a Retry-After header.
// The delay increases exponentially with each retry up to the maximum specified by MaxRetryDelay.
// The default value is four seconds. A value less than zero means no delay between retries.
// The default value is 800 milliseconds. A value less than zero means no delay between retries.
RetryDelay time.Duration
// MaxRetryDelay specifies the maximum delay allowed before retrying an operation.

View File

@@ -32,6 +32,7 @@ type PagingHandler[T any] struct {
}
// Pager provides operations for iterating over paged responses.
// Methods on this type are not safe for concurrent use.
type Pager[T any] struct {
current *T
handler PagingHandler[T]

View File

@@ -51,6 +51,15 @@ func acquire(state acquiringResourceState) (newResource exported.AccessToken, ne
return tk, tk.ExpiresOn, nil
}
// shouldRefresh determines whether the token should be refreshed. It's a variable so tests can replace it.
var shouldRefresh = func(tk exported.AccessToken, _ acquiringResourceState) bool {
if tk.RefreshOn.IsZero() {
return tk.ExpiresOn.Add(-5 * time.Minute).Before(time.Now())
}
// no offset in this case because the authority suggested a refresh window--between RefreshOn and ExpiresOn
return tk.RefreshOn.Before(time.Now())
}
// NewBearerTokenPolicy creates a policy object that authorizes requests with bearer tokens.
// cred: an azcore.TokenCredential implementation such as a credential object from azidentity
// scopes: the list of permission scopes required for the token.
@@ -69,11 +78,14 @@ func NewBearerTokenPolicy(cred exported.TokenCredential, scopes []string, opts *
return authNZ(policy.TokenRequestOptions{Scopes: scopes})
}
}
mr := temporal.NewResourceWithOptions(acquire, temporal.ResourceOptions[exported.AccessToken, acquiringResourceState]{
ShouldRefresh: shouldRefresh,
})
return &BearerTokenPolicy{
authzHandler: ah,
cred: cred,
scopes: scopes,
mainResource: temporal.NewResource(acquire),
mainResource: mr,
allowHTTP: opts.InsecureAllowCredentialWithHTTP,
}
}
@@ -85,7 +97,9 @@ func (b *BearerTokenPolicy) authenticateAndAuthorize(req *policy.Request) func(p
as := acquiringResourceState{p: b, req: req, tro: tro}
tk, err := b.mainResource.Get(as)
if err != nil {
return err
// consider this error non-retriable because if it could be resolved by
// retrying authentication, the credential would have done so already
return errorinfo.NonRetriableError(err)
}
req.Raw().Header.Set(shared.HeaderAuthorization, shared.BearerTokenPrefix+tk.Token)
return nil

View File

@@ -50,8 +50,14 @@ const (
// NewPollerOptions contains the optional parameters for NewPoller.
type NewPollerOptions[T any] struct {
// FinalStateVia contains the final-state-via value for the LRO.
// NOTE: used only for Azure-AsyncOperation and Operation-Location LROs.
FinalStateVia FinalStateVia
// OperationLocationResultPath contains the JSON path to the result's
// payload when it's included with the terminal success response.
// NOTE: only used for Operation-Location LROs.
OperationLocationResultPath string
// Response contains a preconstructed response type.
// The final payload will be unmarshaled into it and returned.
Response *T
@@ -98,7 +104,7 @@ func NewPoller[T any](resp *http.Response, pl exported.Pipeline, options *NewPol
opr, err = async.New[T](pl, resp, options.FinalStateVia)
} else if op.Applicable(resp) {
// op poller must be checked before loc as it can also have a location header
opr, err = op.New[T](pl, resp, options.FinalStateVia)
opr, err = op.New[T](pl, resp, options.FinalStateVia, options.OperationLocationResultPath)
} else if loc.Applicable(resp) {
opr, err = loc.New[T](pl, resp)
} else if body.Applicable(resp) {
@@ -172,7 +178,7 @@ func NewPollerFromResumeToken[T any](token string, pl exported.Pipeline, options
} else if loc.CanResume(asJSON) {
opr, _ = loc.New[T](pl, nil)
} else if op.CanResume(asJSON) {
opr, _ = op.New[T](pl, nil, "")
opr, _ = op.New[T](pl, nil, "", "")
} else {
return nil, fmt.Errorf("unhandled poller token %s", string(raw))
}
@@ -200,6 +206,7 @@ type PollingHandler[T any] interface {
}
// Poller encapsulates a long-running operation, providing polling facilities until the operation reaches a terminal state.
// Methods on this type are not safe for concurrent use.
type Poller[T any] struct {
op PollingHandler[T]
resp *http.Response

View File

@@ -6,6 +6,8 @@
package errorinfo
import "errors"
// NonRetriable represents a non-transient error. This works in
// conjunction with the retry policy, indicating that the error condition
// is idempotent, so no retries will be attempted.
@@ -15,10 +17,14 @@ type NonRetriable interface {
NonRetriable()
}
// NonRetriableError marks the specified error as non-retriable.
// This function takes an error as input and returns a new error that is marked as non-retriable.
// NonRetriableError ensures the specified error is [NonRetriable]. If
// the error is already [NonRetriable], it returns that error unchanged.
// Otherwise, it returns a new, [NonRetriable] error.
func NonRetriableError(err error) error {
return &nonRetriableError{err}
if !errors.As(err, new(NonRetriable)) {
err = &nonRetriableError{err}
}
return err
}
// nonRetriableError is a struct that embeds the error interface.

View File

@@ -44,7 +44,7 @@ func Should(cls Event) bool {
if log.lst == nil {
return false
}
if log.cls == nil || len(log.cls) == 0 {
if len(log.cls) == 0 {
return true
}
for _, c := range log.cls {

View File

@@ -11,9 +11,17 @@ import (
"time"
)
// backoff sets a minimum wait time between eager update attempts. It's a variable so tests can manipulate it.
var backoff = func(now, lastAttempt time.Time) bool {
return lastAttempt.Add(30 * time.Second).After(now)
}
// AcquireResource abstracts a method for refreshing a temporal resource.
type AcquireResource[TResource, TState any] func(state TState) (newResource TResource, newExpiration time.Time, err error)
// ShouldRefresh abstracts a method for indicating whether a resource should be refreshed before expiration.
type ShouldRefresh[TResource, TState any] func(TResource, TState) bool
// Resource is a temporal resource (usually a credential) that requires periodic refreshing.
type Resource[TResource, TState any] struct {
// cond is used to synchronize access to the shared resource embodied by the remaining fields
@@ -31,24 +39,43 @@ type Resource[TResource, TState any] struct {
// lastAttempt indicates when a thread/goroutine last attempted to acquire/update the resource
lastAttempt time.Time
// shouldRefresh indicates whether the resource should be refreshed before expiration
shouldRefresh ShouldRefresh[TResource, TState]
// acquireResource is the callback function that actually acquires the resource
acquireResource AcquireResource[TResource, TState]
}
// NewResource creates a new Resource that uses the specified AcquireResource for refreshing.
func NewResource[TResource, TState any](ar AcquireResource[TResource, TState]) *Resource[TResource, TState] {
return &Resource[TResource, TState]{cond: sync.NewCond(&sync.Mutex{}), acquireResource: ar}
r := &Resource[TResource, TState]{acquireResource: ar, cond: sync.NewCond(&sync.Mutex{})}
r.shouldRefresh = r.expiringSoon
return r
}
// ResourceOptions contains optional configuration for Resource
type ResourceOptions[TResource, TState any] struct {
// ShouldRefresh indicates whether [Resource.Get] should acquire an updated resource despite
// the currently held resource not having expired. [Resource.Get] ignores all errors from
// refresh attempts triggered by ShouldRefresh returning true, and doesn't call ShouldRefresh
// when the resource has expired (it unconditionally updates expired resources). When
// ShouldRefresh is nil, [Resource.Get] refreshes the resource if it will expire within 5
// minutes.
ShouldRefresh ShouldRefresh[TResource, TState]
}
// NewResourceWithOptions creates a new Resource that uses the specified AcquireResource for refreshing.
func NewResourceWithOptions[TResource, TState any](ar AcquireResource[TResource, TState], opts ResourceOptions[TResource, TState]) *Resource[TResource, TState] {
r := NewResource(ar)
if opts.ShouldRefresh != nil {
r.shouldRefresh = opts.ShouldRefresh
}
return r
}
// Get returns the underlying resource.
// If the resource is fresh, no refresh is performed.
func (er *Resource[TResource, TState]) Get(state TState) (TResource, error) {
// If the resource is expiring within this time window, update it eagerly.
// This allows other threads/goroutines to keep running by using the not-yet-expired
// resource value while one thread/goroutine updates the resource.
const window = 5 * time.Minute // This example updates the resource 5 minutes prior to expiration
const backoff = 30 * time.Second // Minimum wait time between eager update attempts
now, acquire, expired := time.Now(), false, false
// acquire exclusive lock
@@ -65,9 +92,8 @@ func (er *Resource[TResource, TState]) Get(state TState) (TResource, error) {
break
}
// Getting here means that this thread/goroutine will wait for the updated resource
} else if er.expiration.Add(-window).Before(now) {
// The resource is valid but is expiring within the time window
if !er.acquiring && er.lastAttempt.Add(backoff).Before(now) {
} else if er.shouldRefresh(resource, state) {
if !(er.acquiring || backoff(now, er.lastAttempt)) {
// If another thread/goroutine is not acquiring/renewing the resource, and none has attempted
// to do so within the last 30 seconds, this thread/goroutine will do it
er.acquiring, acquire = true, true
@@ -121,3 +147,8 @@ func (er *Resource[TResource, TState]) Expire() {
// Reset the expiration as if we never got this resource to begin with
er.expiration = time.Time{}
}
func (er *Resource[TResource, TState]) expiringSoon(TResource, TState) bool {
// call time.Now() instead of using Get's value so ShouldRefresh doesn't need a time.Time parameter
return er.expiration.Add(-5 * time.Minute).Before(time.Now())
}

3
vendor/github.com/ProtonMail/go-crypto/AUTHORS generated vendored Normal file
View File

@@ -0,0 +1,3 @@
# This source code refers to The Go Authors for copyright purposes.
# The master list of authors is in the main Go distribution,
# visible at https://tip.golang.org/AUTHORS.

3
vendor/github.com/ProtonMail/go-crypto/CONTRIBUTORS generated vendored Normal file
View File

@@ -0,0 +1,3 @@
# This source code was written by the Go contributors.
# The master list of contributors is in the main Go distribution,
# visible at https://tip.golang.org/CONTRIBUTORS.

27
vendor/github.com/ProtonMail/go-crypto/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,27 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
vendor/github.com/ProtonMail/go-crypto/PATENTS generated vendored Normal file
View File

@@ -0,0 +1,22 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.

View File

@@ -0,0 +1,381 @@
package bitcurves
// Copyright 2010 The Go Authors. All rights reserved.
// Copyright 2011 ThePiachu. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package bitelliptic implements several Koblitz elliptic curves over prime
// fields.
// This package operates, internally, on Jacobian coordinates. For a given
// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1)
// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole
// calculation can be performed within the transform (as in ScalarMult and
// ScalarBaseMult). But even for Add and Double, it's faster to apply and
// reverse the transform than to operate in affine coordinates.
import (
"crypto/elliptic"
"io"
"math/big"
"sync"
)
// A BitCurve represents a Koblitz Curve with a=0.
// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
type BitCurve struct {
Name string
P *big.Int // the order of the underlying field
N *big.Int // the order of the base point
B *big.Int // the constant of the BitCurve equation
Gx, Gy *big.Int // (x,y) of the base point
BitSize int // the size of the underlying field
}
// Params returns the parameters of the given BitCurve (see BitCurve struct)
func (bitCurve *BitCurve) Params() (cp *elliptic.CurveParams) {
cp = new(elliptic.CurveParams)
cp.Name = bitCurve.Name
cp.P = bitCurve.P
cp.N = bitCurve.N
cp.Gx = bitCurve.Gx
cp.Gy = bitCurve.Gy
cp.BitSize = bitCurve.BitSize
return cp
}
// IsOnCurve returns true if the given (x,y) lies on the BitCurve.
func (bitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool {
// y² = x³ + b
y2 := new(big.Int).Mul(y, y) //y²
y2.Mod(y2, bitCurve.P) //y²%P
x3 := new(big.Int).Mul(x, x) //x²
x3.Mul(x3, x) //x³
x3.Add(x3, bitCurve.B) //x³+B
x3.Mod(x3, bitCurve.P) //(x³+B)%P
return x3.Cmp(y2) == 0
}
// affineFromJacobian reverses the Jacobian transform. See the comment at the
// top of the file.
func (bitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
if z.Cmp(big.NewInt(0)) == 0 {
panic("bitcurve: Can't convert to affine with Jacobian Z = 0")
}
// x = YZ^2 mod P
zinv := new(big.Int).ModInverse(z, bitCurve.P)
zinvsq := new(big.Int).Mul(zinv, zinv)
xOut = new(big.Int).Mul(x, zinvsq)
xOut.Mod(xOut, bitCurve.P)
// y = YZ^3 mod P
zinvsq.Mul(zinvsq, zinv)
yOut = new(big.Int).Mul(y, zinvsq)
yOut.Mod(yOut, bitCurve.P)
return xOut, yOut
}
// Add returns the sum of (x1,y1) and (x2,y2)
func (bitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
z := new(big.Int).SetInt64(1)
x, y, z := bitCurve.addJacobian(x1, y1, z, x2, y2, z)
return bitCurve.affineFromJacobian(x, y, z)
}
// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
// (x2, y2, z2) and returns their sum, also in Jacobian form.
func (bitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
z1z1 := new(big.Int).Mul(z1, z1)
z1z1.Mod(z1z1, bitCurve.P)
z2z2 := new(big.Int).Mul(z2, z2)
z2z2.Mod(z2z2, bitCurve.P)
u1 := new(big.Int).Mul(x1, z2z2)
u1.Mod(u1, bitCurve.P)
u2 := new(big.Int).Mul(x2, z1z1)
u2.Mod(u2, bitCurve.P)
h := new(big.Int).Sub(u2, u1)
if h.Sign() == -1 {
h.Add(h, bitCurve.P)
}
i := new(big.Int).Lsh(h, 1)
i.Mul(i, i)
j := new(big.Int).Mul(h, i)
s1 := new(big.Int).Mul(y1, z2)
s1.Mul(s1, z2z2)
s1.Mod(s1, bitCurve.P)
s2 := new(big.Int).Mul(y2, z1)
s2.Mul(s2, z1z1)
s2.Mod(s2, bitCurve.P)
r := new(big.Int).Sub(s2, s1)
if r.Sign() == -1 {
r.Add(r, bitCurve.P)
}
r.Lsh(r, 1)
v := new(big.Int).Mul(u1, i)
x3 := new(big.Int).Set(r)
x3.Mul(x3, x3)
x3.Sub(x3, j)
x3.Sub(x3, v)
x3.Sub(x3, v)
x3.Mod(x3, bitCurve.P)
y3 := new(big.Int).Set(r)
v.Sub(v, x3)
y3.Mul(y3, v)
s1.Mul(s1, j)
s1.Lsh(s1, 1)
y3.Sub(y3, s1)
y3.Mod(y3, bitCurve.P)
z3 := new(big.Int).Add(z1, z2)
z3.Mul(z3, z3)
z3.Sub(z3, z1z1)
if z3.Sign() == -1 {
z3.Add(z3, bitCurve.P)
}
z3.Sub(z3, z2z2)
if z3.Sign() == -1 {
z3.Add(z3, bitCurve.P)
}
z3.Mul(z3, h)
z3.Mod(z3, bitCurve.P)
return x3, y3, z3
}
// Double returns 2*(x,y)
func (bitCurve *BitCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
z1 := new(big.Int).SetInt64(1)
return bitCurve.affineFromJacobian(bitCurve.doubleJacobian(x1, y1, z1))
}
// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
// returns its double, also in Jacobian form.
func (bitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
a := new(big.Int).Mul(x, x) //X1²
b := new(big.Int).Mul(y, y) //Y1²
c := new(big.Int).Mul(b, b) //B²
d := new(big.Int).Add(x, b) //X1+B
d.Mul(d, d) //(X1+B)²
d.Sub(d, a) //(X1+B)²-A
d.Sub(d, c) //(X1+B)²-A-C
d.Mul(d, big.NewInt(2)) //2*((X1+B)²-A-C)
e := new(big.Int).Mul(big.NewInt(3), a) //3*A
f := new(big.Int).Mul(e, e) //E²
x3 := new(big.Int).Mul(big.NewInt(2), d) //2*D
x3.Sub(f, x3) //F-2*D
x3.Mod(x3, bitCurve.P)
y3 := new(big.Int).Sub(d, x3) //D-X3
y3.Mul(e, y3) //E*(D-X3)
y3.Sub(y3, new(big.Int).Mul(big.NewInt(8), c)) //E*(D-X3)-8*C
y3.Mod(y3, bitCurve.P)
z3 := new(big.Int).Mul(y, z) //Y1*Z1
z3.Mul(big.NewInt(2), z3) //3*Y1*Z1
z3.Mod(z3, bitCurve.P)
return x3, y3, z3
}
// TODO: double check if it is okay
// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
func (bitCurve *BitCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
// We have a slight problem in that the identity of the group (the
// point at infinity) cannot be represented in (x, y) form on a finite
// machine. Thus the standard add/double algorithm has to be tweaked
// slightly: our initial state is not the identity, but x, and we
// ignore the first true bit in |k|. If we don't find any true bits in
// |k|, then we return nil, nil, because we cannot return the identity
// element.
Bz := new(big.Int).SetInt64(1)
x := Bx
y := By
z := Bz
seenFirstTrue := false
for _, byte := range k {
for bitNum := 0; bitNum < 8; bitNum++ {
if seenFirstTrue {
x, y, z = bitCurve.doubleJacobian(x, y, z)
}
if byte&0x80 == 0x80 {
if !seenFirstTrue {
seenFirstTrue = true
} else {
x, y, z = bitCurve.addJacobian(Bx, By, Bz, x, y, z)
}
}
byte <<= 1
}
}
if !seenFirstTrue {
return nil, nil
}
return bitCurve.affineFromJacobian(x, y, z)
}
// ScalarBaseMult returns k*G, where G is the base point of the group and k is
// an integer in big-endian form.
func (bitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
return bitCurve.ScalarMult(bitCurve.Gx, bitCurve.Gy, k)
}
var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
// TODO: double check if it is okay
// GenerateKey returns a public/private key pair. The private key is generated
// using the given reader, which must return random data.
func (bitCurve *BitCurve) GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err error) {
byteLen := (bitCurve.BitSize + 7) >> 3
priv = make([]byte, byteLen)
for x == nil {
_, err = io.ReadFull(rand, priv)
if err != nil {
return
}
// We have to mask off any excess bits in the case that the size of the
// underlying field is not a whole number of bytes.
priv[0] &= mask[bitCurve.BitSize%8]
// This is because, in tests, rand will return all zeros and we don't
// want to get the point at infinity and loop forever.
priv[1] ^= 0x42
x, y = bitCurve.ScalarBaseMult(priv)
}
return
}
// Marshal converts a point into the form specified in section 4.3.6 of ANSI
// X9.62.
func (bitCurve *BitCurve) Marshal(x, y *big.Int) []byte {
byteLen := (bitCurve.BitSize + 7) >> 3
ret := make([]byte, 1+2*byteLen)
ret[0] = 4 // uncompressed point
xBytes := x.Bytes()
copy(ret[1+byteLen-len(xBytes):], xBytes)
yBytes := y.Bytes()
copy(ret[1+2*byteLen-len(yBytes):], yBytes)
return ret
}
// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On
// error, x = nil.
func (bitCurve *BitCurve) Unmarshal(data []byte) (x, y *big.Int) {
byteLen := (bitCurve.BitSize + 7) >> 3
if len(data) != 1+2*byteLen {
return
}
if data[0] != 4 { // uncompressed form
return
}
x = new(big.Int).SetBytes(data[1 : 1+byteLen])
y = new(big.Int).SetBytes(data[1+byteLen:])
return
}
//curve parameters taken from:
//http://www.secg.org/collateral/sec2_final.pdf
var initonce sync.Once
var secp160k1 *BitCurve
var secp192k1 *BitCurve
var secp224k1 *BitCurve
var secp256k1 *BitCurve
func initAll() {
initS160()
initS192()
initS224()
initS256()
}
func initS160() {
// See SEC 2 section 2.4.1
secp160k1 = new(BitCurve)
secp160k1.Name = "secp160k1"
secp160k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", 16)
secp160k1.N, _ = new(big.Int).SetString("0100000000000000000001B8FA16DFAB9ACA16B6B3", 16)
secp160k1.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000007", 16)
secp160k1.Gx, _ = new(big.Int).SetString("3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", 16)
secp160k1.Gy, _ = new(big.Int).SetString("938CF935318FDCED6BC28286531733C3F03C4FEE", 16)
secp160k1.BitSize = 160
}
func initS192() {
// See SEC 2 section 2.5.1
secp192k1 = new(BitCurve)
secp192k1.Name = "secp192k1"
secp192k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", 16)
secp192k1.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", 16)
secp192k1.B, _ = new(big.Int).SetString("000000000000000000000000000000000000000000000003", 16)
secp192k1.Gx, _ = new(big.Int).SetString("DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", 16)
secp192k1.Gy, _ = new(big.Int).SetString("9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", 16)
secp192k1.BitSize = 192
}
func initS224() {
// See SEC 2 section 2.6.1
secp224k1 = new(BitCurve)
secp224k1.Name = "secp224k1"
secp224k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", 16)
secp224k1.N, _ = new(big.Int).SetString("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", 16)
secp224k1.B, _ = new(big.Int).SetString("00000000000000000000000000000000000000000000000000000005", 16)
secp224k1.Gx, _ = new(big.Int).SetString("A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", 16)
secp224k1.Gy, _ = new(big.Int).SetString("7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", 16)
secp224k1.BitSize = 224
}
func initS256() {
// See SEC 2 section 2.7.1
secp256k1 = new(BitCurve)
secp256k1.Name = "secp256k1"
secp256k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16)
secp256k1.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
secp256k1.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000007", 16)
secp256k1.Gx, _ = new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16)
secp256k1.Gy, _ = new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16)
secp256k1.BitSize = 256
}
// S160 returns a BitCurve which implements secp160k1 (see SEC 2 section 2.4.1)
func S160() *BitCurve {
initonce.Do(initAll)
return secp160k1
}
// S192 returns a BitCurve which implements secp192k1 (see SEC 2 section 2.5.1)
func S192() *BitCurve {
initonce.Do(initAll)
return secp192k1
}
// S224 returns a BitCurve which implements secp224k1 (see SEC 2 section 2.6.1)
func S224() *BitCurve {
initonce.Do(initAll)
return secp224k1
}
// S256 returns a BitCurve which implements bitcurves (see SEC 2 section 2.7.1)
func S256() *BitCurve {
initonce.Do(initAll)
return secp256k1
}

View File

@@ -0,0 +1,134 @@
// Package brainpool implements Brainpool elliptic curves.
// Implementation of rcurves is from github.com/ebfe/brainpool
// Note that these curves are implemented with naive, non-constant time operations
// and are likely not suitable for environments where timing attacks are a concern.
package brainpool
import (
"crypto/elliptic"
"math/big"
"sync"
)
var (
once sync.Once
p256t1, p384t1, p512t1 *elliptic.CurveParams
p256r1, p384r1, p512r1 *rcurve
)
func initAll() {
initP256t1()
initP384t1()
initP512t1()
initP256r1()
initP384r1()
initP512r1()
}
func initP256t1() {
p256t1 = &elliptic.CurveParams{Name: "brainpoolP256t1"}
p256t1.P, _ = new(big.Int).SetString("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16)
p256t1.N, _ = new(big.Int).SetString("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16)
p256t1.B, _ = new(big.Int).SetString("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16)
p256t1.Gx, _ = new(big.Int).SetString("A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4", 16)
p256t1.Gy, _ = new(big.Int).SetString("2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE", 16)
p256t1.BitSize = 256
}
func initP256r1() {
twisted := p256t1
params := &elliptic.CurveParams{
Name: "brainpoolP256r1",
P: twisted.P,
N: twisted.N,
BitSize: twisted.BitSize,
}
params.Gx, _ = new(big.Int).SetString("8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", 16)
params.Gy, _ = new(big.Int).SetString("547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", 16)
z, _ := new(big.Int).SetString("3E2D4BD9597B58639AE7AA669CAB9837CF5CF20A2C852D10F655668DFC150EF0", 16)
p256r1 = newrcurve(twisted, params, z)
}
func initP384t1() {
p384t1 = &elliptic.CurveParams{Name: "brainpoolP384t1"}
p384t1.P, _ = new(big.Int).SetString("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16)
p384t1.N, _ = new(big.Int).SetString("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16)
p384t1.B, _ = new(big.Int).SetString("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16)
p384t1.Gx, _ = new(big.Int).SetString("18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC", 16)
p384t1.Gy, _ = new(big.Int).SetString("25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928", 16)
p384t1.BitSize = 384
}
func initP384r1() {
twisted := p384t1
params := &elliptic.CurveParams{
Name: "brainpoolP384r1",
P: twisted.P,
N: twisted.N,
BitSize: twisted.BitSize,
}
params.Gx, _ = new(big.Int).SetString("1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", 16)
params.Gy, _ = new(big.Int).SetString("8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", 16)
z, _ := new(big.Int).SetString("41DFE8DD399331F7166A66076734A89CD0D2BCDB7D068E44E1F378F41ECBAE97D2D63DBC87BCCDDCCC5DA39E8589291C", 16)
p384r1 = newrcurve(twisted, params, z)
}
func initP512t1() {
p512t1 = &elliptic.CurveParams{Name: "brainpoolP512t1"}
p512t1.P, _ = new(big.Int).SetString("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16)
p512t1.N, _ = new(big.Int).SetString("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16)
p512t1.B, _ = new(big.Int).SetString("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16)
p512t1.Gx, _ = new(big.Int).SetString("640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA", 16)
p512t1.Gy, _ = new(big.Int).SetString("5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332", 16)
p512t1.BitSize = 512
}
func initP512r1() {
twisted := p512t1
params := &elliptic.CurveParams{
Name: "brainpoolP512r1",
P: twisted.P,
N: twisted.N,
BitSize: twisted.BitSize,
}
params.Gx, _ = new(big.Int).SetString("81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", 16)
params.Gy, _ = new(big.Int).SetString("7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", 16)
z, _ := new(big.Int).SetString("12EE58E6764838B69782136F0F2D3BA06E27695716054092E60A80BEDB212B64E585D90BCE13761F85C3F1D2A64E3BE8FEA2220F01EBA5EEB0F35DBD29D922AB", 16)
p512r1 = newrcurve(twisted, params, z)
}
// P256t1 returns a Curve which implements Brainpool P256t1 (see RFC 5639, section 3.4)
func P256t1() elliptic.Curve {
once.Do(initAll)
return p256t1
}
// P256r1 returns a Curve which implements Brainpool P256r1 (see RFC 5639, section 3.4)
func P256r1() elliptic.Curve {
once.Do(initAll)
return p256r1
}
// P384t1 returns a Curve which implements Brainpool P384t1 (see RFC 5639, section 3.6)
func P384t1() elliptic.Curve {
once.Do(initAll)
return p384t1
}
// P384r1 returns a Curve which implements Brainpool P384r1 (see RFC 5639, section 3.6)
func P384r1() elliptic.Curve {
once.Do(initAll)
return p384r1
}
// P512t1 returns a Curve which implements Brainpool P512t1 (see RFC 5639, section 3.7)
func P512t1() elliptic.Curve {
once.Do(initAll)
return p512t1
}
// P512r1 returns a Curve which implements Brainpool P512r1 (see RFC 5639, section 3.7)
func P512r1() elliptic.Curve {
once.Do(initAll)
return p512r1
}

View File

@@ -0,0 +1,83 @@
package brainpool
import (
"crypto/elliptic"
"math/big"
)
var _ elliptic.Curve = (*rcurve)(nil)
type rcurve struct {
twisted elliptic.Curve
params *elliptic.CurveParams
z *big.Int
zinv *big.Int
z2 *big.Int
z3 *big.Int
zinv2 *big.Int
zinv3 *big.Int
}
var (
two = big.NewInt(2)
three = big.NewInt(3)
)
func newrcurve(twisted elliptic.Curve, params *elliptic.CurveParams, z *big.Int) *rcurve {
zinv := new(big.Int).ModInverse(z, params.P)
return &rcurve{
twisted: twisted,
params: params,
z: z,
zinv: zinv,
z2: new(big.Int).Exp(z, two, params.P),
z3: new(big.Int).Exp(z, three, params.P),
zinv2: new(big.Int).Exp(zinv, two, params.P),
zinv3: new(big.Int).Exp(zinv, three, params.P),
}
}
func (curve *rcurve) toTwisted(x, y *big.Int) (*big.Int, *big.Int) {
var tx, ty big.Int
tx.Mul(x, curve.z2)
tx.Mod(&tx, curve.params.P)
ty.Mul(y, curve.z3)
ty.Mod(&ty, curve.params.P)
return &tx, &ty
}
func (curve *rcurve) fromTwisted(tx, ty *big.Int) (*big.Int, *big.Int) {
var x, y big.Int
x.Mul(tx, curve.zinv2)
x.Mod(&x, curve.params.P)
y.Mul(ty, curve.zinv3)
y.Mod(&y, curve.params.P)
return &x, &y
}
func (curve *rcurve) Params() *elliptic.CurveParams {
return curve.params
}
func (curve *rcurve) IsOnCurve(x, y *big.Int) bool {
return curve.twisted.IsOnCurve(curve.toTwisted(x, y))
}
func (curve *rcurve) Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int) {
tx1, ty1 := curve.toTwisted(x1, y1)
tx2, ty2 := curve.toTwisted(x2, y2)
return curve.fromTwisted(curve.twisted.Add(tx1, ty1, tx2, ty2))
}
func (curve *rcurve) Double(x1, y1 *big.Int) (x, y *big.Int) {
return curve.fromTwisted(curve.twisted.Double(curve.toTwisted(x1, y1)))
}
func (curve *rcurve) ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int) {
tx1, ty1 := curve.toTwisted(x1, y1)
return curve.fromTwisted(curve.twisted.ScalarMult(tx1, ty1, scalar))
}
func (curve *rcurve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
return curve.fromTwisted(curve.twisted.ScalarBaseMult(scalar))
}

162
vendor/github.com/ProtonMail/go-crypto/eax/eax.go generated vendored Normal file
View File

@@ -0,0 +1,162 @@
// Copyright (C) 2019 ProtonTech AG
// Package eax provides an implementation of the EAX
// (encrypt-authenticate-translate) mode of operation, as described in
// Bellare, Rogaway, and Wagner "THE EAX MODE OF OPERATION: A TWO-PASS
// AUTHENTICATED-ENCRYPTION SCHEME OPTIMIZED FOR SIMPLICITY AND EFFICIENCY."
// In FSE'04, volume 3017 of LNCS, 2004
package eax
import (
"crypto/cipher"
"crypto/subtle"
"errors"
"github.com/ProtonMail/go-crypto/internal/byteutil"
)
const (
defaultTagSize = 16
defaultNonceSize = 16
)
type eax struct {
block cipher.Block // Only AES-{128, 192, 256} supported
tagSize int // At least 12 bytes recommended
nonceSize int
}
func (e *eax) NonceSize() int {
return e.nonceSize
}
func (e *eax) Overhead() int {
return e.tagSize
}
// NewEAX returns an EAX instance with AES-{KEYLENGTH} and default nonce and
// tag lengths. Supports {128, 192, 256}- bit key length.
func NewEAX(block cipher.Block) (cipher.AEAD, error) {
return NewEAXWithNonceAndTagSize(block, defaultNonceSize, defaultTagSize)
}
// NewEAXWithNonceAndTagSize returns an EAX instance with AES-{keyLength} and
// given nonce and tag lengths in bytes. Panics on zero nonceSize and
// exceedingly long tags.
//
// It is recommended to use at least 12 bytes as tag length (see, for instance,
// NIST SP 800-38D).
//
// Only to be used for compatibility with existing cryptosystems with
// non-standard parameters. For all other cases, prefer NewEAX.
func NewEAXWithNonceAndTagSize(
block cipher.Block, nonceSize, tagSize int) (cipher.AEAD, error) {
if nonceSize < 1 {
return nil, eaxError("Cannot initialize EAX with nonceSize = 0")
}
if tagSize > block.BlockSize() {
return nil, eaxError("Custom tag length exceeds blocksize")
}
return &eax{
block: block,
tagSize: tagSize,
nonceSize: nonceSize,
}, nil
}
func (e *eax) Seal(dst, nonce, plaintext, adata []byte) []byte {
if len(nonce) > e.nonceSize {
panic("crypto/eax: Nonce too long for this instance")
}
ret, out := byteutil.SliceForAppend(dst, len(plaintext)+e.tagSize)
omacNonce := e.omacT(0, nonce)
omacAdata := e.omacT(1, adata)
// Encrypt message using CTR mode and omacNonce as IV
ctr := cipher.NewCTR(e.block, omacNonce)
ciphertextData := out[:len(plaintext)]
ctr.XORKeyStream(ciphertextData, plaintext)
omacCiphertext := e.omacT(2, ciphertextData)
tag := out[len(plaintext):]
for i := 0; i < e.tagSize; i++ {
tag[i] = omacCiphertext[i] ^ omacNonce[i] ^ omacAdata[i]
}
return ret
}
func (e *eax) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) {
if len(nonce) > e.nonceSize {
panic("crypto/eax: Nonce too long for this instance")
}
if len(ciphertext) < e.tagSize {
return nil, eaxError("Ciphertext shorter than tag length")
}
sep := len(ciphertext) - e.tagSize
// Compute tag
omacNonce := e.omacT(0, nonce)
omacAdata := e.omacT(1, adata)
omacCiphertext := e.omacT(2, ciphertext[:sep])
tag := make([]byte, e.tagSize)
for i := 0; i < e.tagSize; i++ {
tag[i] = omacCiphertext[i] ^ omacNonce[i] ^ omacAdata[i]
}
// Compare tags
if subtle.ConstantTimeCompare(ciphertext[sep:], tag) != 1 {
return nil, eaxError("Tag authentication failed")
}
// Decrypt ciphertext
ret, out := byteutil.SliceForAppend(dst, len(ciphertext))
ctr := cipher.NewCTR(e.block, omacNonce)
ctr.XORKeyStream(out, ciphertext[:sep])
return ret[:sep], nil
}
// Tweakable OMAC - Calls OMAC_K([t]_n || plaintext)
func (e *eax) omacT(t byte, plaintext []byte) []byte {
blockSize := e.block.BlockSize()
byteT := make([]byte, blockSize)
byteT[blockSize-1] = t
concat := append(byteT, plaintext...)
return e.omac(concat)
}
func (e *eax) omac(plaintext []byte) []byte {
blockSize := e.block.BlockSize()
// L ← E_K(0^n); B ← 2L; P ← 4L
L := make([]byte, blockSize)
e.block.Encrypt(L, L)
B := byteutil.GfnDouble(L)
P := byteutil.GfnDouble(B)
// CBC with IV = 0
cbc := cipher.NewCBCEncrypter(e.block, make([]byte, blockSize))
padded := e.pad(plaintext, B, P)
cbcCiphertext := make([]byte, len(padded))
cbc.CryptBlocks(cbcCiphertext, padded)
return cbcCiphertext[len(cbcCiphertext)-blockSize:]
}
func (e *eax) pad(plaintext, B, P []byte) []byte {
// if |M| in {n, 2n, 3n, ...}
blockSize := e.block.BlockSize()
if len(plaintext) != 0 && len(plaintext)%blockSize == 0 {
return byteutil.RightXor(plaintext, B)
}
// else return (M || 1 || 0^(n1(|M| % n))) xor→ P
ending := make([]byte, blockSize-len(plaintext)%blockSize)
ending[0] = 0x80
padded := append(plaintext, ending...)
return byteutil.RightXor(padded, P)
}
func eaxError(err string) error {
return errors.New("crypto/eax: " + err)
}

View File

@@ -0,0 +1,58 @@
package eax
// Test vectors from
// https://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf
var testVectors = []struct {
msg, key, nonce, header, ciphertext string
}{
{"",
"233952DEE4D5ED5F9B9C6D6FF80FF478",
"62EC67F9C3A4A407FCB2A8C49031A8B3",
"6BFB914FD07EAE6B",
"E037830E8389F27B025A2D6527E79D01"},
{"F7FB",
"91945D3F4DCBEE0BF45EF52255F095A4",
"BECAF043B0A23D843194BA972C66DEBD",
"FA3BFD4806EB53FA",
"19DD5C4C9331049D0BDAB0277408F67967E5"},
{"1A47CB4933",
"01F74AD64077F2E704C0F60ADA3DD523",
"70C3DB4F0D26368400A10ED05D2BFF5E",
"234A3463C1264AC6",
"D851D5BAE03A59F238A23E39199DC9266626C40F80"},
{"481C9E39B1",
"D07CF6CBB7F313BDDE66B727AFD3C5E8",
"8408DFFF3C1A2B1292DC199E46B7D617",
"33CCE2EABFF5A79D",
"632A9D131AD4C168A4225D8E1FF755939974A7BEDE"},
{"40D0C07DA5E4",
"35B6D0580005BBC12B0587124557D2C2",
"FDB6B06676EEDC5C61D74276E1F8E816",
"AEB96EAEBE2970E9",
"071DFE16C675CB0677E536F73AFE6A14B74EE49844DD"},
{"4DE3B35C3FC039245BD1FB7D",
"BD8E6E11475E60B268784C38C62FEB22",
"6EAC5C93072D8E8513F750935E46DA1B",
"D4482D1CA78DCE0F",
"835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F"},
{"8B0A79306C9CE7ED99DAE4F87F8DD61636",
"7C77D6E813BED5AC98BAA417477A2E7D",
"1A8C98DCD73D38393B2BF1569DEEFC19",
"65D2017990D62528",
"02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2"},
{"1BDA122BCE8A8DBAF1877D962B8592DD2D56",
"5FFF20CAFAB119CA2FC73549E20F5B0D",
"DDE59B97D722156D4D9AFF2BC7559826",
"54B9F04E6A09189A",
"2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A"},
{"6CF36720872B8513F6EAB1A8A44438D5EF11",
"A4A4782BCFFD3EC5E7EF6D8C34A56123",
"B781FCF2F75FA5A8DE97A9CA48E522EC",
"899A175897561D7E",
"0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700"},
{"CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7",
"8395FCF1E95BEBD697BD010BC766AAC3",
"22E7ADD93CFC6393C57EC0B3C17D6B44",
"126735FCC320D25A",
"CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E"},
}

View File

@@ -0,0 +1,131 @@
// These vectors include key length in {128, 192, 256}, tag size 128, and
// random nonce, header, and plaintext lengths.
// This file was automatically generated.
package eax
var randomVectors = []struct {
key, nonce, header, plaintext, ciphertext string
}{
{"DFDE093F36B0356E5A81F609786982E3",
"1D8AC604419001816905BA72B14CED7E",
"152A1517A998D7A24163FCDD146DE81AC347C8B97088F502093C1ABB8F6E33D9A219C34D7603A18B1F5ABE02E56661B7D7F67E81EC08C1302EF38D80A859486D450E94A4F26AD9E68EEBBC0C857A0FC5CF9E641D63D565A7E361BC8908F5A8DC8FD6",
"1C8EAAB71077FE18B39730A3156ADE29C5EE824C7EE86ED2A253B775603FB237116E654F6FEC588DD27F523A0E01246FE73FE348491F2A8E9ABC6CA58D663F71CDBCF4AD798BE46C42AE6EE8B599DB44A1A48D7BBBBA0F7D2750181E1C5E66967F7D57CBD30AFBDA5727",
"79E7E150934BBEBF7013F61C60462A14D8B15AF7A248AFB8A344EF021C1500E16666891D6E973D8BB56B71A371F12CA34660C4410C016982B20F547E3762A58B7BF4F20236CADCF559E2BE7D783B13723B2741FC7CDC8997D839E39A3DDD2BADB96743DD7049F1BDB0516A262869915B3F70498AFB7B191BF960"},
{"F10619EF02E5D94D7550EB84ED364A21",
"8DC0D4F2F745BBAE835CC5574B942D20",
"FE561358F2E8DF7E1024FF1AE9A8D36EBD01352214505CB99D644777A8A1F6027FA2BDBFC529A9B91136D5F2416CFC5F0F4EC3A1AFD32BDDA23CA504C5A5CB451785FABF4DFE4CD50D817491991A60615B30286361C100A95D1712F2A45F8E374461F4CA2B",
"D7B5A971FC219631D30EFC3664AE3127D9CF3097DAD9C24AC7905D15E8D9B25B026B31D68CAE00975CDB81EB1FD96FD5E1A12E2BB83FA25F1B1D91363457657FC03875C27F2946C5",
"2F336ED42D3CC38FC61660C4CD60BA4BD438B05F5965D8B7B399D2E7167F5D34F792D318F94DB15D67463AC449E13D568CC09BFCE32A35EE3EE96A041927680AE329811811E27F2D1E8E657707AF99BA96D13A478D695D59"},
{"429F514EFC64D98A698A9247274CFF45",
"976AA5EB072F912D126ACEBC954FEC38",
"A71D89DC5B6CEDBB7451A27C3C2CAE09126DB4C421",
"5632FE62AB1DC549D54D3BC3FC868ACCEDEFD9ECF5E9F8",
"848AE4306CA8C7F416F8707625B7F55881C0AB430353A5C967CDA2DA787F581A70E34DBEBB2385"},
{"398138F309085F47F8457CDF53895A63",
"F8A8A7F2D28E5FFF7BBC2F24353F7A36",
"5D633C21BA7764B8855CAB586F3746E236AD486039C83C6B56EFA9C651D38A41D6B20DAEE3418BFEA44B8BD6",
"A3BBAA91920AF5E10659818B1B3B300AC79BFC129C8329E75251F73A66D3AE0128EB91D5031E0A65C329DB7D1E9C0493E268",
"D078097267606E5FB07CFB7E2B4B718172A82C6A4CEE65D549A4DFB9838003BD2FBF64A7A66988AC1A632FD88F9E9FBB57C5A78AD2E086EACBA3DB68511D81C2970A"},
{"7A4151EBD3901B42CBA45DAFB2E931BA",
"0FC88ACEE74DD538040321C330974EB8",
"250464FB04733BAB934C59E6AD2D6AE8D662CBCFEFBE61E5A308D4211E58C4C25935B72C69107722E946BFCBF416796600542D76AEB73F2B25BF53BAF97BDEB36ED3A7A51C31E7F170EB897457E7C17571D1BA0A908954E9",
"88C41F3EBEC23FAB8A362D969CAC810FAD4F7CA6A7F7D0D44F060F92E37E1183768DD4A8C733F71C96058D362A39876D183B86C103DE",
"74A25B2182C51096D48A870D80F18E1CE15867778E34FCBA6BD7BFB3739FDCD42AD0F2D9F4EBA29085285C6048C15BCE5E5166F1F962D3337AA88E6062F05523029D0A7F0BF9"},
{"BFB147E1CD5459424F8C0271FC0E0DC5",
"EABCC126442BF373969EA3015988CC45",
"4C0880E1D71AA2C7",
"BE1B5EC78FBF73E7A6682B21BA7E0E5D2D1C7ABE",
"5660D7C1380E2F306895B1402CB2D6C37876504276B414D120F4CF92FDDDBB293A238EA0"},
{"595DD6F52D18BC2CA8EB4EDAA18D9FA3",
"0F84B5D36CF4BC3B863313AF3B4D2E97",
"30AE6CC5F99580F12A779D98BD379A60948020C0B6FBD5746B30BA3A15C6CD33DAF376C70A9F15B6C0EB410A93161F7958AE23",
"8EF3687A1642B070970B0B91462229D1D76ABC154D18211F7152AA9FF368",
"317C1DDB11417E5A9CC4DDE7FDFF6659A5AC4B31DE025212580A05CDAC6024D3E4AE7C2966E52B9129E9ECDBED86"},
{"44E6F2DC8FDC778AD007137D11410F50",
"270A237AD977F7187AA6C158A0BAB24F",
"509B0F0EB12E2AA5C5BA2DE553C07FAF4CE0C9E926531AA709A3D6224FCB783ACCF1559E10B1123EBB7D52E8AB54E6B5352A9ED0D04124BF0E9D9BACFD7E32B817B2E625F5EE94A64EDE9E470DE7FE6886C19B294F9F828209FE257A78",
"8B3D7815DF25618A5D0C55A601711881483878F113A12EC36CF64900549A3199555528559DC118F789788A55FAFD944E6E99A9CA3F72F238CD3F4D88223F7A745992B3FAED1848",
"1CC00D79F7AD82FDA71B58D286E5F34D0CC4CEF30704E771CC1E50746BDF83E182B078DB27149A42BAE619DF0F85B0B1090AD55D3B4471B0D6F6ECCD09C8F876B30081F0E7537A9624F8AAF29DA85E324122EFB4D68A56"},
{"BB7BC352A03044B4428D8DBB4B0701FDEC4649FD17B81452",
"8B4BBE26CCD9859DCD84884159D6B0A4",
"2212BEB0E78E0F044A86944CF33C8D5C80D9DBE1034BF3BCF73611835C7D3A52F5BD2D81B68FD681B68540A496EE5DA16FD8AC8824E60E1EC2042BE28FB0BFAD4E4B03596446BDD8C37D936D9B3D5295BE19F19CF5ACE1D33A46C952CE4DE5C12F92C1DD051E04AEED",
"9037234CC44FFF828FABED3A7084AF40FA7ABFF8E0C0EFB57A1CC361E18FC4FAC1AB54F3ABFE9FF77263ACE16C3A",
"A9391B805CCD956081E0B63D282BEA46E7025126F1C1631239C33E92AA6F92CD56E5A4C56F00FF9658E93D48AF4EF0EF81628E34AD4DB0CDAEDCD2A17EE7"},
{"99C0AD703196D2F60A74E6B378B838B31F82EA861F06FC4E",
"92745C018AA708ECFEB1667E9F3F1B01",
"828C69F376C0C0EC651C67749C69577D589EE39E51404D80EBF70C8660A8F5FD375473F4A7C611D59CB546A605D67446CE2AA844135FCD78BB5FBC90222A00D42920BB1D7EEDFB0C4672554F583EF23184F89063CDECBE482367B5F9AF3ACBC3AF61392BD94CBCD9B64677",
"A879214658FD0A5B0E09836639BF82E05EC7A5EF71D4701934BDA228435C68AC3D5CEB54997878B06A655EEACEFB1345C15867E7FE6C6423660C8B88DF128EBD6BCD85118DBAE16E9252FFB204324E5C8F38CA97759BDBF3CB0083",
"51FE87996F194A2585E438B023B345439EA60D1AEBED4650CDAF48A4D4EEC4FC77DC71CC4B09D3BEEF8B7B7AF716CE2B4EFFB3AC9E6323C18AC35E0AA6E2BBBC8889490EB6226C896B0D105EAB42BFE7053CCF00ED66BA94C1BA09A792AA873F0C3B26C5C5F9A936E57B25"},
{"7086816D00D648FB8304AA8C9E552E1B69A9955FB59B25D1",
"0F45CF7F0BF31CCEB85D9DA10F4D749F",
"93F27C60A417D9F0669E86ACC784FC8917B502DAF30A6338F11B30B94D74FEFE2F8BE1BBE2EAD10FAB7EED3C6F72B7C3ECEE1937C32ED4970A6404E139209C05",
"877F046601F3CBE4FB1491943FA29487E738F94B99AF206262A1D6FF856C9AA0B8D4D08A54370C98F8E88FA3DCC2B14C1F76D71B2A4C7963AEE8AF960464C5BEC8357AD00DC8",
"FE96906B895CE6A8E72BC72344E2C8BB3C63113D70EAFA26C299BAFE77A8A6568172EB447FB3E86648A0AF3512DEB1AAC0819F3EC553903BF28A9FB0F43411237A774BF9EE03E445D280FBB9CD12B9BAAB6EF5E52691"},
{"062F65A896D5BF1401BADFF70E91B458E1F9BD4888CB2E4D",
"5B11EA1D6008EBB41CF892FCA5B943D1",
"BAF4FF5C8242",
"A8870E091238355984EB2F7D61A865B9170F440BFF999A5993DD41A10F4440D21FF948DDA2BF663B2E03AC3324492DC5E40262ECC6A65C07672353BE23E7FB3A9D79FF6AA38D97960905A38DECC312CB6A59E5467ECF06C311CD43ADC0B543EDF34FE8BE611F176460D5627CA51F8F8D9FED71F55C",
"B10E127A632172CF8AA7539B140D2C9C2590E6F28C3CB892FC498FCE56A34F732FBFF32E79C7B9747D9094E8635A0C084D6F0247F9768FB5FF83493799A9BEC6C39572120C40E9292C8C947AE8573462A9108C36D9D7112E6995AE5867E6C8BB387D1C5D4BEF524F391B9FD9F0A3B4BFA079E915BCD920185CFD38D114C558928BD7D47877"},
{"38A8E45D6D705A11AF58AED5A1344896998EACF359F2E26A",
"FD82B5B31804FF47D44199B533D0CF84",
"DE454D4E62FE879F2050EE3E25853623D3E9AC52EEC1A1779A48CFAF5ECA0BFDE44749391866D1",
"B804",
"164BB965C05EBE0931A1A63293EDF9C38C27"},
{"34C33C97C6D7A0850DA94D78A58DC61EC717CD7574833068",
"343BE00DA9483F05C14F2E9EB8EA6AE8",
"78312A43EFDE3CAE34A65796FF059A3FE15304EEA5CF1D9306949FE5BF3349D4977D4EBE76C040FE894C5949E4E4D6681153DA87FB9AC5062063CA2EA183566343362370944CE0362D25FC195E124FD60E8682E665D13F2229DDA3E4B2CB1DCA",
"CC11BB284B1153578E4A5ED9D937B869DAF00F5B1960C23455CA9CC43F486A3BE0B66254F1041F04FDF459C8640465B6E1D2CF899A381451E8E7FCB50CF87823BE77E24B132BBEEDC72E53369B275E1D8F49ECE59F4F215230AC4FE133FC80E4F634EE80BA4682B62C86",
"E7F703DC31A95E3A4919FF957836CB76C063D81702AEA4703E1C2BF30831E58C4609D626EC6810E12EAA5B930F049FF9EFC22C3E3F1EBD4A1FB285CB02A1AC5AD46B425199FC0A85670A5C4E3DAA9636C8F64C199F42F18AAC8EA7457FD377F322DD7752D7D01B946C8F0A97E6113F0D50106F319AFD291AAACE"},
{"C6ECF7F053573E403E61B83052A343D93CBCC179D1E835BE",
"E280E13D7367042E3AA09A80111B6184",
"21486C9D7A9647",
"5F2639AFA6F17931853791CD8C92382BBB677FD72D0AB1A080D0E49BFAA21810E963E4FACD422E92F65CBFAD5884A60CD94740DF31AF02F95AA57DA0C4401B0ED906",
"5C51DB20755302070C45F52E50128A67C8B2E4ED0EACB7E29998CCE2E8C289DD5655913EC1A51CC3AABE5CDC2402B2BE7D6D4BF6945F266FBD70BA9F37109067157AE7530678B45F64475D4EBFCB5FFF46A5"},
{"5EC6CF7401BC57B18EF154E8C38ACCA8959E57D2F3975FF5",
"656B41CB3F9CF8C08BAD7EBFC80BD225",
"6B817C2906E2AF425861A7EF59BA5801F143EE2A139EE72697CDE168B4",
"2C0E1DDC9B1E5389BA63845B18B1F8A1DB062037151BCC56EF7C21C0BB4DAE366636BBA975685D7CC5A94AFBE89C769016388C56FB7B57CE750A12B718A8BDCF70E80E8659A8330EFC8F86640F21735E8C80E23FE43ABF23507CE3F964AE4EC99D",
"ED780CF911E6D1AA8C979B889B0B9DC1ABE261832980BDBFB576901D9EF5AB8048998E31A15BE54B3E5845A4D136AD24D0BDA1C3006168DF2F8AC06729CB0818867398150020131D8F04EDF1923758C9EABB5F735DE5EA1758D4BC0ACFCA98AFD202E9839B8720253693B874C65586C6F0"},
{"C92F678EB2208662F5BCF3403EC05F5961E957908A3E79421E1D25FC19054153",
"DA0F3A40983D92F2D4C01FED33C7A192",
"2B6E9D26DB406A0FAB47608657AA10EFC2B4AA5F459B29FF85AC9A40BFFE7AEB04F77E9A11FAAA116D7F6D4DA417671A9AB02C588E0EF59CB1BFB4B1CC931B63A3B3A159FCEC97A04D1E6F0C7E6A9CEF6B0ABB04758A69F1FE754DF4C2610E8C46B6CF413BDB31351D55BEDCB7B4A13A1C98E10984475E0F2F957853",
"F37326A80E08",
"83519E53E321D334F7C10B568183775C0E9AAE55F806"},
{"6847E0491BE57E72995D186D50094B0B3593957A5146798FCE68B287B2FB37B5",
"3EE1182AEBB19A02B128F28E1D5F7F99",
"D9F35ABB16D776CE",
"DB7566ED8EA95BDF837F23DB277BAFBC5E70D1105ADFD0D9EF15475051B1EF94709C67DCA9F8D5",
"2CDCED0C9EBD6E2A508822A685F7DCD1CDD99E7A5FCA786C234E7F7F1D27EC49751AD5DCFA30C5EDA87C43CAE3B919B6BBCFE34C8EDA59"},
{"82B019673642C08388D3E42075A4D5D587558C229E4AB8F660E37650C4C41A0A",
"336F5D681E0410FAE7B607246092C6DC",
"D430CBD8FE435B64214E9E9CDC5DE99D31CFCFB8C10AA0587A49DF276611",
"998404153AD77003E1737EDE93ED79859EE6DCCA93CB40C4363AA817ABF2DBBD46E42A14A7183B6CC01E12A577888141363D0AE011EB6E8D28C0B235",
"9BEF69EEB60BD3D6065707B7557F25292A8872857CFBD24F2F3C088E4450995333088DA50FD9121221C504DF1D0CD5EFE6A12666C5D5BB12282CF4C19906E9CFAB97E9BDF7F49DC17CFC384B"},
{"747B2E269B1859F0622C15C8BAD6A725028B1F94B8DB7326948D1E6ED663A8BC",
"AB91F7245DDCE3F1C747872D47BE0A8A",
"3B03F786EF1DDD76E1D42646DA4CD2A5165DC5383CE86D1A0B5F13F910DC278A4E451EE0192CBA178E13B3BA27FDC7840DF73D2E104B",
"6B803F4701114F3E5FE21718845F8416F70F626303F545BE197189E0A2BA396F37CE06D389EB2658BC7D56D67868708F6D0D32",
"1570DDB0BCE75AA25D1957A287A2C36B1A5F2270186DA81BA6112B7F43B0F3D1D0ED072591DCF1F1C99BBB25621FC39B896FF9BD9413A2845363A9DCD310C32CF98E57"},
{"02E59853FB29AEDA0FE1C5F19180AD99A12FF2F144670BB2B8BADF09AD812E0A",
"C691294EF67CD04D1B9242AF83DD1421",
"879334DAE3",
"1E17F46A98FEF5CBB40759D95354",
"FED8C3FF27DDF6313AED444A2985B36CBA268AAD6AAC563C0BA28F6DB5DB"},
{"F6C1FB9B4188F2288FF03BD716023198C3582CF2A037FC2F29760916C2B7FCDB",
"4228DA0678CA3534588859E77DFF014C",
"D8153CAF35539A61DD8D05B3C9B44F01E564FB9348BCD09A1C23B84195171308861058F0A3CD2A55B912A3AAEE06FF4D356C77275828F2157C2FC7C115DA39E443210CCC56BEDB0CC99BBFB227ABD5CC454F4E7F547C7378A659EEB6A7E809101A84F866503CB18D4484E1FA09B3EC7FC75EB2E35270800AA7",
"23B660A779AD285704B12EC1C580387A47BEC7B00D452C6570",
"5AA642BBABA8E49849002A2FAF31DB8FC7773EFDD656E469CEC19B3206D4174C9A263D0A05484261F6"},
{"8FF6086F1FADB9A3FBE245EAC52640C43B39D43F89526BB5A6EBA47710931446",
"943188480C99437495958B0AE4831AA9",
"AD5CD0BDA426F6EBA23C8EB23DC73FF9FEC173355EDBD6C9344C4C4383F211888F7CE6B29899A6801DF6B38651A7C77150941A",
"80CD5EA8D7F81DDF5070B934937912E8F541A5301877528EB41AB60C020968D459960ED8FB73083329841A",
"ABAE8EB7F36FCA2362551E72DAC890BA1BB6794797E0FC3B67426EC9372726ED4725D379EA0AC9147E48DCD0005C502863C2C5358A38817C8264B5"},
{"A083B54E6B1FE01B65D42FCD248F97BB477A41462BBFE6FD591006C022C8FD84",
"B0490F5BD68A52459556B3749ACDF40E",
"8892E047DA5CFBBDF7F3CFCBD1BD21C6D4C80774B1826999234394BD3E513CC7C222BB40E1E3140A152F19B3802F0D036C24A590512AD0E8",
"D7B15752789DC94ED0F36778A5C7BBB207BEC32BAC66E702B39966F06E381E090C6757653C3D26A81EC6AD6C364D66867A334C91BB0B8A8A4B6EACDF0783D09010AEBA2DD2062308FE99CC1F",
"C071280A732ADC93DF272BF1E613B2BB7D46FC6665EF2DC1671F3E211D6BDE1D6ADDD28DF3AA2E47053FC8BB8AE9271EC8BC8B2CFFA320D225B451685B6D23ACEFDD241FE284F8ADC8DB07F456985B14330BBB66E0FB212213E05B3E"},
}

View File

@@ -0,0 +1,90 @@
// Copyright (C) 2019 ProtonTech AG
// This file contains necessary tools for the aex and ocb packages.
//
// These functions SHOULD NOT be used elsewhere, since they are optimized for
// specific input nature in the EAX and OCB modes of operation.
package byteutil
// GfnDouble computes 2 * input in the field of 2^n elements.
// The irreducible polynomial in the finite field for n=128 is
// x^128 + x^7 + x^2 + x + 1 (equals 0x87)
// Constant-time execution in order to avoid side-channel attacks
func GfnDouble(input []byte) []byte {
if len(input) != 16 {
panic("Doubling in GFn only implemented for n = 128")
}
// If the first bit is zero, return 2L = L << 1
// Else return (L << 1) xor 0^120 10000111
shifted := ShiftBytesLeft(input)
shifted[15] ^= ((input[0] >> 7) * 0x87)
return shifted
}
// ShiftBytesLeft outputs the byte array corresponding to x << 1 in binary.
func ShiftBytesLeft(x []byte) []byte {
l := len(x)
dst := make([]byte, l)
for i := 0; i < l-1; i++ {
dst[i] = (x[i] << 1) | (x[i+1] >> 7)
}
dst[l-1] = x[l-1] << 1
return dst
}
// ShiftNBytesLeft puts in dst the byte array corresponding to x << n in binary.
func ShiftNBytesLeft(dst, x []byte, n int) {
// Erase first n / 8 bytes
copy(dst, x[n/8:])
// Shift the remaining n % 8 bits
bits := uint(n % 8)
l := len(dst)
for i := 0; i < l-1; i++ {
dst[i] = (dst[i] << bits) | (dst[i+1] >> uint(8-bits))
}
dst[l-1] = dst[l-1] << bits
// Append trailing zeroes
dst = append(dst, make([]byte, n/8)...)
}
// XorBytesMut replaces X with X XOR Y. len(X) must be >= len(Y).
func XorBytesMut(X, Y []byte) {
for i := 0; i < len(Y); i++ {
X[i] ^= Y[i]
}
}
// XorBytes puts X XOR Y into Z. len(Z) and len(X) must be >= len(Y).
func XorBytes(Z, X, Y []byte) {
for i := 0; i < len(Y); i++ {
Z[i] = X[i] ^ Y[i]
}
}
// RightXor XORs smaller input (assumed Y) at the right of the larger input (assumed X)
func RightXor(X, Y []byte) []byte {
offset := len(X) - len(Y)
xored := make([]byte, len(X))
copy(xored, X)
for i := 0; i < len(Y); i++ {
xored[offset+i] ^= Y[i]
}
return xored
}
// SliceForAppend takes a slice and a requested number of bytes. It returns a
// slice with the contents of the given slice followed by that many bytes and a
// second slice that aliases into it and contains only the extra bytes. If the
// original slice has sufficient capacity then no allocation is performed.
func SliceForAppend(in []byte, n int) (head, tail []byte) {
if total := len(in) + n; cap(in) >= total {
head = in[:total]
} else {
head = make([]byte, total)
copy(head, in)
}
tail = head[len(in):]
return
}

313
vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go generated vendored Normal file
View File

@@ -0,0 +1,313 @@
// Copyright (C) 2019 ProtonTech AG
// Package ocb provides an implementation of the OCB (offset codebook) mode of
// operation, as described in RFC-7253 of the IRTF and in Rogaway, Bellare,
// Black and Krovetz - OCB: A BLOCK-CIPHER MODE OF OPERATION FOR EFFICIENT
// AUTHENTICATED ENCRYPTION (2003).
// Security considerations (from RFC-7253): A private key MUST NOT be used to
// encrypt more than 2^48 blocks. Tag length should be at least 12 bytes (a
// brute-force forging adversary succeeds after 2^{tag length} attempts). A
// single key SHOULD NOT be used to decrypt ciphertext with different tag
// lengths. Nonces need not be secret, but MUST NOT be reused.
// This package only supports underlying block ciphers with 128-bit blocks,
// such as AES-{128, 192, 256}, but may be extended to other sizes.
package ocb
import (
"bytes"
"crypto/cipher"
"crypto/subtle"
"errors"
"math/bits"
"github.com/ProtonMail/go-crypto/internal/byteutil"
)
type ocb struct {
block cipher.Block
tagSize int
nonceSize int
mask mask
// Optimized en/decrypt: For each nonce N used to en/decrypt, the 'Ktop'
// internal variable can be reused for en/decrypting with nonces sharing
// all but the last 6 bits with N. The prefix of the first nonce used to
// compute the new Ktop, and the Ktop value itself, are stored in
// reusableKtop. If using incremental nonces, this saves one block cipher
// call every 63 out of 64 OCB encryptions, and stores one nonce and one
// output of the block cipher in memory only.
reusableKtop reusableKtop
}
type mask struct {
// L_*, L_$, (L_i)_{i ∈ N}
lAst []byte
lDol []byte
L [][]byte
}
type reusableKtop struct {
noncePrefix []byte
Ktop []byte
}
const (
defaultTagSize = 16
defaultNonceSize = 15
)
const (
enc = iota
dec
)
func (o *ocb) NonceSize() int {
return o.nonceSize
}
func (o *ocb) Overhead() int {
return o.tagSize
}
// NewOCB returns an OCB instance with the given block cipher and default
// tag and nonce sizes.
func NewOCB(block cipher.Block) (cipher.AEAD, error) {
return NewOCBWithNonceAndTagSize(block, defaultNonceSize, defaultTagSize)
}
// NewOCBWithNonceAndTagSize returns an OCB instance with the given block
// cipher, nonce length, and tag length. Panics on zero nonceSize and
// exceedingly long tag size.
//
// It is recommended to use at least 12 bytes as tag length.
func NewOCBWithNonceAndTagSize(
block cipher.Block, nonceSize, tagSize int) (cipher.AEAD, error) {
if block.BlockSize() != 16 {
return nil, ocbError("Block cipher must have 128-bit blocks")
}
if nonceSize < 1 {
return nil, ocbError("Incorrect nonce length")
}
if nonceSize >= block.BlockSize() {
return nil, ocbError("Nonce length exceeds blocksize - 1")
}
if tagSize > block.BlockSize() {
return nil, ocbError("Custom tag length exceeds blocksize")
}
return &ocb{
block: block,
tagSize: tagSize,
nonceSize: nonceSize,
mask: initializeMaskTable(block),
reusableKtop: reusableKtop{
noncePrefix: nil,
Ktop: nil,
},
}, nil
}
func (o *ocb) Seal(dst, nonce, plaintext, adata []byte) []byte {
if len(nonce) > o.nonceSize {
panic("crypto/ocb: Incorrect nonce length given to OCB")
}
sep := len(plaintext)
ret, out := byteutil.SliceForAppend(dst, sep+o.tagSize)
tag := o.crypt(enc, out[:sep], nonce, adata, plaintext)
copy(out[sep:], tag)
return ret
}
func (o *ocb) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) {
if len(nonce) > o.nonceSize {
panic("Nonce too long for this instance")
}
if len(ciphertext) < o.tagSize {
return nil, ocbError("Ciphertext shorter than tag length")
}
sep := len(ciphertext) - o.tagSize
ret, out := byteutil.SliceForAppend(dst, sep)
ciphertextData := ciphertext[:sep]
tag := o.crypt(dec, out, nonce, adata, ciphertextData)
if subtle.ConstantTimeCompare(tag, ciphertext[sep:]) == 1 {
return ret, nil
}
for i := range out {
out[i] = 0
}
return nil, ocbError("Tag authentication failed")
}
// On instruction enc (resp. dec), crypt is the encrypt (resp. decrypt)
// function. It writes the resulting plain/ciphertext into Y and returns
// the tag.
func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte {
//
// Consider X as a sequence of 128-bit blocks
//
// Note: For encryption (resp. decryption), X is the plaintext (resp., the
// ciphertext without the tag).
blockSize := o.block.BlockSize()
//
// Nonce-dependent and per-encryption variables
//
// Zero out the last 6 bits of the nonce into truncatedNonce to see if Ktop
// is already computed.
truncatedNonce := make([]byte, len(nonce))
copy(truncatedNonce, nonce)
truncatedNonce[len(truncatedNonce)-1] &= 192
var Ktop []byte
if bytes.Equal(truncatedNonce, o.reusableKtop.noncePrefix) {
Ktop = o.reusableKtop.Ktop
} else {
// Nonce = num2str(TAGLEN mod 128, 7) || zeros(120 - bitlen(N)) || 1 || N
paddedNonce := append(make([]byte, blockSize-1-len(nonce)), 1)
paddedNonce = append(paddedNonce, truncatedNonce...)
paddedNonce[0] |= byte(((8 * o.tagSize) % (8 * blockSize)) << 1)
// Last 6 bits of paddedNonce are already zero. Encrypt into Ktop
paddedNonce[blockSize-1] &= 192
Ktop = paddedNonce
o.block.Encrypt(Ktop, Ktop)
o.reusableKtop.noncePrefix = truncatedNonce
o.reusableKtop.Ktop = Ktop
}
// Stretch = Ktop || ((lower half of Ktop) XOR (lower half of Ktop << 8))
xorHalves := make([]byte, blockSize/2)
byteutil.XorBytes(xorHalves, Ktop[:blockSize/2], Ktop[1:1+blockSize/2])
stretch := append(Ktop, xorHalves...)
bottom := int(nonce[len(nonce)-1] & 63)
offset := make([]byte, len(stretch))
byteutil.ShiftNBytesLeft(offset, stretch, bottom)
offset = offset[:blockSize]
//
// Process any whole blocks
//
// Note: For encryption Y is ciphertext || tag, for decryption Y is
// plaintext || tag.
checksum := make([]byte, blockSize)
m := len(X) / blockSize
for i := 0; i < m; i++ {
index := bits.TrailingZeros(uint(i + 1))
if len(o.mask.L)-1 < index {
o.mask.extendTable(index)
}
byteutil.XorBytesMut(offset, o.mask.L[bits.TrailingZeros(uint(i+1))])
blockX := X[i*blockSize : (i+1)*blockSize]
blockY := Y[i*blockSize : (i+1)*blockSize]
switch instruction {
case enc:
byteutil.XorBytesMut(checksum, blockX)
byteutil.XorBytes(blockY, blockX, offset)
o.block.Encrypt(blockY, blockY)
byteutil.XorBytesMut(blockY, offset)
case dec:
byteutil.XorBytes(blockY, blockX, offset)
o.block.Decrypt(blockY, blockY)
byteutil.XorBytesMut(blockY, offset)
byteutil.XorBytesMut(checksum, blockY)
}
}
//
// Process any final partial block and compute raw tag
//
tag := make([]byte, blockSize)
if len(X)%blockSize != 0 {
byteutil.XorBytesMut(offset, o.mask.lAst)
pad := make([]byte, blockSize)
o.block.Encrypt(pad, offset)
chunkX := X[blockSize*m:]
chunkY := Y[blockSize*m : len(X)]
switch instruction {
case enc:
byteutil.XorBytesMut(checksum, chunkX)
checksum[len(chunkX)] ^= 128
byteutil.XorBytes(chunkY, chunkX, pad[:len(chunkX)])
// P_* || bit(1) || zeroes(127) - len(P_*)
case dec:
byteutil.XorBytes(chunkY, chunkX, pad[:len(chunkX)])
// P_* || bit(1) || zeroes(127) - len(P_*)
byteutil.XorBytesMut(checksum, chunkY)
checksum[len(chunkY)] ^= 128
}
}
byteutil.XorBytes(tag, checksum, offset)
byteutil.XorBytesMut(tag, o.mask.lDol)
o.block.Encrypt(tag, tag)
byteutil.XorBytesMut(tag, o.hash(adata))
return tag[:o.tagSize]
}
// This hash function is used to compute the tag. Per design, on empty input it
// returns a slice of zeros, of the same length as the underlying block cipher
// block size.
func (o *ocb) hash(adata []byte) []byte {
//
// Consider A as a sequence of 128-bit blocks
//
A := make([]byte, len(adata))
copy(A, adata)
blockSize := o.block.BlockSize()
//
// Process any whole blocks
//
sum := make([]byte, blockSize)
offset := make([]byte, blockSize)
m := len(A) / blockSize
for i := 0; i < m; i++ {
chunk := A[blockSize*i : blockSize*(i+1)]
index := bits.TrailingZeros(uint(i + 1))
// If the mask table is too short
if len(o.mask.L)-1 < index {
o.mask.extendTable(index)
}
byteutil.XorBytesMut(offset, o.mask.L[index])
byteutil.XorBytesMut(chunk, offset)
o.block.Encrypt(chunk, chunk)
byteutil.XorBytesMut(sum, chunk)
}
//
// Process any final partial block; compute final hash value
//
if len(A)%blockSize != 0 {
byteutil.XorBytesMut(offset, o.mask.lAst)
// Pad block with 1 || 0 ^ 127 - bitlength(a)
ending := make([]byte, blockSize-len(A)%blockSize)
ending[0] = 0x80
encrypted := append(A[blockSize*m:], ending...)
byteutil.XorBytesMut(encrypted, offset)
o.block.Encrypt(encrypted, encrypted)
byteutil.XorBytesMut(sum, encrypted)
}
return sum
}
func initializeMaskTable(block cipher.Block) mask {
//
// Key-dependent variables
//
lAst := make([]byte, block.BlockSize())
block.Encrypt(lAst, lAst)
lDol := byteutil.GfnDouble(lAst)
L := make([][]byte, 1)
L[0] = byteutil.GfnDouble(lDol)
return mask{
lAst: lAst,
lDol: lDol,
L: L,
}
}
// Extends the L array of mask m up to L[limit], with L[i] = GfnDouble(L[i-1])
func (m *mask) extendTable(limit int) {
for i := len(m.L); i <= limit; i++ {
m.L = append(m.L, byteutil.GfnDouble(m.L[i-1]))
}
}
func ocbError(err string) error {
return errors.New("crypto/ocb: " + err)
}

View File

@@ -0,0 +1,136 @@
// In the test vectors provided by RFC 7253, the "bottom"
// internal variable, which defines "offset" for the first time, does not
// exceed 15. However, it can attain values up to 63.
// These vectors include key length in {128, 192, 256}, tag size 128, and
// random nonce, header, and plaintext lengths.
// This file was automatically generated.
package ocb
var randomVectors = []struct {
key, nonce, header, plaintext, ciphertext string
}{
{"9438C5D599308EAF13F800D2D31EA7F0",
"C38EE4801BEBFFA1CD8635BE",
"0E507B7DADD8A98CDFE272D3CB6B3E8332B56AE583FB049C0874D4200BED16BD1A044182434E9DA0E841F182DFD5B3016B34641CED0784F1745F63AB3D0DA22D3351C9EF9A658B8081E24498EBF61FCE40DA6D8E184536",
"962D227786FB8913A8BAD5DC3250",
"EEDEF5FFA5986D1E3BF86DDD33EF9ADC79DCA06E215FA772CCBA814F63AD"},
{"BA7DE631C7D6712167C6724F5B9A2B1D",
"35263EBDA05765DC0E71F1F5",
"0103257B4224507C0242FEFE821EA7FA42E0A82863E5F8B68F7D881B4B44FA428A2B6B21D2F591260802D8AB6D83",
"9D6D1FC93AE8A64E7889B7B2E3521EFA9B920A8DDB692E6F833DDC4A38AFA535E5E2A3ED82CB7E26404AB86C54D01C4668F28398C2DF33D5D561CBA1C8DCFA7A912F5048E545B59483C0E3221F54B14DAA2E4EB657B3BEF9554F34CAD69B2724AE962D3D8A",
"E93852D1985C5E775655E937FA79CE5BF28A585F2AF53A5018853B9634BE3C84499AC0081918FDCE0624494D60E25F76ACD6853AC7576E3C350F332249BFCABD4E73CEABC36BE4EDDA40914E598AE74174A0D7442149B26990899491BDDFE8FC54D6C18E83AE9E9A6FFBF5D376565633862EEAD88D"},
{"2E74B25289F6FD3E578C24866E9C72A5",
"FD912F15025AF8414642BA1D1D",
"FB5FB8C26F365EEDAB5FE260C6E3CCD27806729C8335F146063A7F9EA93290E56CF84576EB446350D22AD730547C267B1F0BBB97EB34E1E2C41A",
"6C092EBF78F76EE8C1C6E592277D9545BA16EDB67BC7D8480B9827702DC2F8A129E2B08A2CE710CA7E1DA45CE162BB6CD4B512E632116E2211D3C90871EFB06B8D4B902681C7FB",
"6AC0A77F26531BF4F354A1737F99E49BE32ECD909A7A71AD69352906F54B08A9CE9B8CA5D724CBFFC5673437F23F630697F3B84117A1431D6FA8CC13A974FB4AD360300522E09511B99E71065D5AC4BBCB1D791E864EF4"},
{"E7EC507C802528F790AFF5303A017B17",
"4B97A7A568940A9E3CE7A99E93031E",
"28349BDC5A09390C480F9B8AA3EDEA3DDB8B9D64BCA322C570B8225DF0E31190DAB25A4014BA39519E02ABFB12B89AA28BBFD29E486E7FB28734258C817B63CED9912DBAFEBB93E2798AB2890DE3B0ACFCFF906AB15563EF7823CE83D27CDB251195E22BD1337BCBDE65E7C2C427321C463C2777BFE5AEAA",
"9455B3EA706B74",
"7F33BA3EA848D48A96B9530E26888F43EBD4463C9399B6"},
{"6C928AA3224736F28EE7378DE0090191",
"8936138E2E4C6A13280017A1622D",
"6202717F2631565BDCDC57C6584543E72A7C8BD444D0D108ED35069819633C",
"DA0691439E5F035F3E455269D14FE5C201C8C9B0A3FE2D3F86BCC59387C868FE65733D388360B31E3CE28B4BF6A8BE636706B536D5720DB66B47CF1C7A5AFD6F61E0EF90F1726D6B0E169F9A768B2B7AE4EE00A17F630AC905FCAAA1B707FFF25B3A1AAE83B504837C64A5639B2A34002B300EC035C9B43654DA55",
"B8804D182AB0F0EEB464FA7BD1329AD6154F982013F3765FEDFE09E26DAC078C9C1439BFC1159D6C02A25E3FF83EF852570117B315852AD5EE20E0FA3AA0A626B0E43BC0CEA38B44579DD36803455FB46989B90E6D229F513FD727AF8372517E9488384C515D6067704119C931299A0982EDDFB9C2E86A90C450C077EB222511EC9CCABC9FCFDB19F70088"},
{"ECEA315CA4B3F425B0C9957A17805EA4",
"664CDAE18403F4F9BA13015A44FC",
"642AFB090D6C6DB46783F08B01A3EF2A8FEB5736B531EAC226E7888FCC8505F396818F83105065FACB3267485B9E5E4A0261F621041C08FCCB2A809A49AB5252A91D0971BCC620B9D614BD77E57A0EED2FA5",
"6852C31F8083E20E364CEA21BB7854D67CEE812FE1C9ED2425C0932A90D3780728D1BB",
"2ECEF962A9695A463ADABB275BDA9FF8B2BA57AEC2F52EFFB700CD9271A74D2A011C24AEA946051BD6291776429B7E681BA33E"},
{"4EE616C4A58AAA380878F71A373461F6",
"91B8C9C176D9C385E9C47E52",
"CDA440B7F9762C572A718AC754EDEECC119E5EE0CCB9FEA4FFB22EEE75087C032EBF3DA9CDD8A28CC010B99ED45143B41A4BA50EA2A005473F89639237838867A57F23B0F0ED3BF22490E4501DAC9C658A9B9F",
"D6E645FA9AE410D15B8123FD757FA356A8DBE9258DDB5BE88832E615910993F497EC",
"B70ED7BF959FB2AAED4F36174A2A99BFB16992C8CDF369C782C4DB9C73DE78C5DB8E0615F647243B97ACDB24503BC9CADC48"},
{"DCD475773136C830D5E3D0C5FE05B7FF",
"BB8E1FBB483BE7616A922C4A",
"36FEF2E1CB29E76A6EA663FC3AF66ECD7404F466382F7B040AABED62293302B56E8783EF7EBC21B4A16C3E78A7483A0A403F253A2CDC5BBF79DC3DAE6C73F39A961D8FBBE8D41B",
"441E886EA38322B2437ECA7DEB5282518865A66780A454E510878E61BFEC3106A3CD93D2A02052E6F9E1832F9791053E3B76BF4C07EFDD6D4106E3027FABB752E60C1AA425416A87D53938163817A1051EBA1D1DEEB4B9B25C7E97368B52E5911A31810B0EC5AF547559B6142D9F4C4A6EF24A4CF75271BF9D48F62B",
"1BE4DD2F4E25A6512C2CC71D24BBB07368589A94C2714962CD0ACE5605688F06342587521E75F0ACAFFD86212FB5C34327D238DB36CF2B787794B9A4412E7CD1410EA5DDD2450C265F29CF96013CD213FD2880657694D718558964BC189B4A84AFCF47EB012935483052399DBA5B088B0A0477F20DFE0E85DCB735E21F22A439FB837DD365A93116D063E607"},
{"3FBA2B3D30177FFE15C1C59ED2148BB2C091F5615FBA7C07",
"FACF804A4BEBF998505FF9DE",
"8213B9263B2971A5BDA18DBD02208EE1",
"15B323926993B326EA19F892D704439FC478828322AF72118748284A1FD8A6D814E641F70512FD706980337379F31DC63355974738D7FEA87AD2858C0C2EBBFBE74371C21450072373C7B651B334D7C4D43260B9D7CCD3AF9EDB",
"6D35DC1469B26E6AAB26272A41B46916397C24C485B61162E640A062D9275BC33DDCFD3D9E1A53B6C8F51AC89B66A41D59B3574197A40D9B6DCF8A4E2A001409C8112F16B9C389E0096179DB914E05D6D11ED0005AD17E1CE105A2F0BAB8F6B1540DEB968B7A5428FF44"},
{"53B52B8D4D748BCDF1DDE68857832FA46227FA6E2F32EFA1",
"0B0EF53D4606B28D1398355F",
"F23882436349094AF98BCACA8218E81581A043B19009E28EFBF2DE37883E04864148CC01D240552CA8844EC1456F42034653067DA67E80F87105FD06E14FF771246C9612867BE4D215F6D761",
"F15030679BD4088D42CAC9BF2E9606EAD4798782FA3ED8C57EBE7F84A53236F51B25967C6489D0CD20C9EEA752F9BC",
"67B96E2D67C3729C96DAEAEDF821D61C17E648643A2134C5621FEC621186915AD80864BFD1EB5B238BF526A679385E012A457F583AFA78134242E9D9C1B4E4"},
{"0272DD80F23399F49BFC320381A5CD8225867245A49A7D41",
"5C83F4896D0738E1366B1836",
"69B0337289B19F73A12BAEEA857CCAF396C11113715D9500CCCF48BA08CFF12BC8B4BADB3084E63B85719DB5058FA7C2C11DEB096D7943CFA7CAF5",
"C01AD10FC8B562CD17C7BC2FAB3E26CBDFF8D7F4DEA816794BBCC12336991712972F52816AABAB244EB43B0137E2BAC1DD413CE79531E78BEF782E6B439612BB3AEF154DE3502784F287958EBC159419F9EBA27916A28D6307324129F506B1DE80C1755A929F87",
"FEFE52DD7159C8DD6E8EC2D3D3C0F37AB6CB471A75A071D17EC4ACDD8F3AA4D7D4F7BB559F3C09099E3D9003E5E8AA1F556B79CECDE66F85B08FA5955E6976BF2695EA076388A62D2AD5BAB7CBF1A7F3F4C8D5CDF37CDE99BD3E30B685D9E5EEE48C7C89118EF4878EB89747F28271FA2CC45F8E9E7601"},
{"3EEAED04A455D6E5E5AB53CFD5AFD2F2BC625C7BF4BE49A5",
"36B88F63ADBB5668588181D774",
"D367E3CB3703E762D23C6533188EF7028EFF9D935A3977150361997EC9DEAF1E4794BDE26AA8B53C124980B1362EC86FCDDFC7A90073171C1BAEE351A53234B86C66E8AB92FAE99EC6967A6D3428892D80",
"573454C719A9A55E04437BF7CBAAF27563CCCD92ADD5E515CD63305DFF0687E5EEF790C5DCA5C0033E9AB129505E2775438D92B38F08F3B0356BA142C6F694",
"E9F79A5B432D9E682C9AAA5661CFC2E49A0FCB81A431E54B42EB73DD3BED3F377FEC556ABA81624BA64A5D739AD41467460088F8D4F442180A9382CA635745473794C382FCDDC49BA4EB6D8A44AE3C"},
{"B695C691538F8CBD60F039D0E28894E3693CC7C36D92D79D",
"BC099AEB637361BAC536B57618",
"BFFF1A65AE38D1DC142C71637319F5F6508E2CB33C9DCB94202B359ED5A5ED8042E7F4F09231D32A7242976677E6F4C549BF65FADC99E5AF43F7A46FD95E16C2",
"081DF3FD85B415D803F0BE5AC58CFF0023FDDED99788296C3731D8",
"E50C64E3614D94FE69C47092E46ACC9957C6FEA2CCBF96BC62FBABE7424753C75F9C147C42AE26FE171531"},
{"C9ACBD2718F0689A1BE9802A551B6B8D9CF5614DAF5E65ED",
"B1B0AAF373B8B026EB80422051D8",
"6648C0E61AC733C76119D23FB24548D637751387AA2EAE9D80E912B7BD486CAAD9EAF4D7A5FE2B54AAD481E8EC94BB4D558000896E2010462B70C9FED1E7273080D1",
"189F591F6CB6D59AFEDD14C341741A8F1037DC0DF00FC57CE65C30F49E860255CEA5DC6019380CC0FE8880BC1A9E685F41C239C38F36E3F2A1388865C5C311059C0A",
"922A5E949B61D03BE34AB5F4E58607D4504EA14017BB363DAE3C873059EA7A1C77A746FB78981671D26C2CF6D9F24952D510044CE02A10177E9DB42D0145211DFE6E84369C5E3BC2669EAB4147B2822895F9"},
{"7A832BD2CF5BF4919F353CE2A8C86A5E406DA2D52BE16A72",
"2F2F17CECF7E5A756D10785A3CB9DB",
"61DA05E3788CC2D8405DBA70C7A28E5AF699863C9F72E6C6770126929F5D6FA267F005EBCF49495CB46400958A3AE80D1289D1C671",
"44E91121195A41AF14E8CFDBD39A4B517BE0DF1A72977ED8A3EEF8EEDA1166B2EB6DB2C4AE2E74FA0F0C74537F659BFBD141E5DDEC67E64EDA85AABD3F52C85A785B9FB3CECD70E7DF",
"BEDF596EA21288D2B84901E188F6EE1468B14D5161D3802DBFE00D60203A24E2AB62714BF272A45551489838C3A7FEAADC177B591836E73684867CCF4E12901DCF2064058726BBA554E84ADC5136F507E961188D4AF06943D3"},
{"1508E8AE9079AA15F1CEC4F776B4D11BCCB061B58AA56C18",
"BCA625674F41D1E3AB47672DC0C3",
"8B12CF84F16360F0EAD2A41BC021530FFCEC7F3579CAE658E10E2D3D81870F65AFCED0C77C6C4C6E6BA424FF23088C796BA6195ABA35094BF1829E089662E7A95FC90750AE16D0C8AFA55DAC789D7735B970B58D4BE7CEC7341DA82A0179A01929C27A59C5063215B859EA43",
"E525422519ECE070E82C",
"B47BC07C3ED1C0A43BA52C43CBACBCDBB29CAF1001E09FDF7107"},
{"7550C2761644E911FE9ADD119BAC07376BEA442845FEAD876D7E7AC1B713E464",
"36D2EC25ADD33CDEDF495205BBC923",
"7FCFE81A3790DE97FFC3DE160C470847EA7E841177C2F759571CBD837EA004A6CA8C6F4AEBFF2E9FD552D73EB8A30705D58D70C0B67AEEA280CBBF0A477358ACEF1E7508F2735CD9A0E4F9AC92B8C008F575D3B6278F1C18BD01227E3502E5255F3AB1893632AD00C717C588EF652A51A43209E7EE90",
"2B1A62F8FDFAA3C16470A21AD307C9A7D03ADE8EF72C69B06F8D738CDE578D7AEFD0D40BD9C022FB9F580DF5394C998ACCCEFC5471A3996FB8F1045A81FDC6F32D13502EA65A211390C8D882B8E0BEFD8DD8CBEF51D1597B124E9F7F",
"C873E02A22DB89EB0787DB6A60B99F7E4A0A085D5C4232A81ADCE2D60AA36F92DDC33F93DD8640AC0E08416B187FB382B3EC3EE85A64B0E6EE41C1366A5AD2A282F66605E87031CCBA2FA7B2DA201D975994AADE3DD1EE122AE09604AD489B84BF0C1AB7129EE16C6934850E"},
{"A51300285E554FDBDE7F771A9A9A80955639DD87129FAEF74987C91FB9687C71",
"81691D5D20EC818FCFF24B33DECC",
"C948093218AA9EB2A8E44A87EEA73FC8B6B75A196819A14BD83709EA323E8DF8B491045220E1D88729A38DBCFFB60D3056DAD4564498FD6574F74512945DEB34B69329ACED9FFC05D5D59DFCD5B973E2ACAFE6AD1EF8BBBC49351A2DD12508ED89ED",
"EB861165DAF7625F827C6B574ED703F03215",
"C6CD1CE76D2B3679C1B5AA1CFD67CCB55444B6BFD3E22C81CBC9BB738796B83E54E3"},
{"8CE0156D26FAEB7E0B9B800BBB2E9D4075B5EAC5C62358B0E7F6FCE610223282",
"D2A7B94DD12CDACA909D3AD7",
"E021A78F374FC271389AB9A3E97077D755",
"7C26000B58929F5095E1CEE154F76C2A299248E299F9B5ADE6C403AA1FD4A67FD4E0232F214CE7B919EE7A1027D2B76C57475715CD078461",
"C556FB38DF069B56F337B5FF5775CE6EAA16824DFA754F20B78819028EA635C3BB7AA731DE8776B2DCB67DCA2D33EEDF3C7E52EA450013722A41755A0752433ED17BDD5991AAE77A"},
{"1E8000A2CE00A561C9920A30BF0D7B983FEF8A1014C8F04C35CA6970E6BA02BD",
"65ED3D63F79F90BBFD19775E",
"336A8C0B7243582A46B221AA677647FCAE91",
"134A8B34824A290E7B",
"914FBEF80D0E6E17F8BDBB6097EBF5FBB0554952DC2B9E5151"},
{"53D5607BBE690B6E8D8F6D97F3DF2BA853B682597A214B8AA0EA6E598650AF15",
"C391A856B9FE234E14BA1AC7BB40FF",
"479682BC21349C4BE1641D5E78FE2C79EC1B9CF5470936DCAD9967A4DCD7C4EFADA593BC9EDE71E6A08829B8580901B61E274227E9D918502DE3",
"EAD154DC09C5E26C5D26FF33ED148B27120C7F2C23225CC0D0631B03E1F6C6D96FEB88C1A4052ACB4CE746B884B6502931F407021126C6AAB8C514C077A5A38438AE88EE",
"938821286EBB671D999B87C032E1D6055392EB564E57970D55E545FC5E8BAB90E6E3E3C0913F6320995FC636D72CD9919657CC38BD51552F4A502D8D1FE56DB33EBAC5092630E69EBB986F0E15CEE9FC8C052501"},
{"294362FCC984F440CEA3E9F7D2C06AF20C53AAC1B3738CA2186C914A6E193ABB",
"B15B61C8BB39261A8F55AB178EC3",
"D0729B6B75BB",
"2BD089ADCE9F334BAE3B065996C7D616DD0C27DF4218DCEEA0FBCA0F968837CE26B0876083327E25681FDDD620A32EC0DA12F73FAE826CC94BFF2B90A54D2651",
"AC94B25E4E21DE2437B806966CCD5D9385EF0CD4A51AB9FA6DE675C7B8952D67802E9FEC1FDE9F5D1EAB06057498BC0EEA454804FC9D2068982A3E24182D9AC2E7AB9994DDC899A604264583F63D066B"},
{"959DBFEB039B1A5B8CE6A44649B602AAA5F98A906DB96143D202CD2024F749D9",
"01D7BDB1133E9C347486C1EFA6",
"F3843955BD741F379DD750585EDC55E2CDA05CCBA8C1F4622AC2FE35214BC3A019B8BD12C4CC42D9213D1E1556941E8D8450830287FFB3B763A13722DD4140ED9846FB5FFF745D7B0B967D810A068222E10B259AF1D392035B0D83DC1498A6830B11B2418A840212599171E0258A1C203B05362978",
"A21811232C950FA8B12237C2EBD6A7CD2C3A155905E9E0C7C120",
"63C1CE397B22F1A03F1FA549B43178BC405B152D3C95E977426D519B3DFCA28498823240592B6EEE7A14"},
{"096AE499F5294173F34FF2B375F0E5D5AB79D0D03B33B1A74D7D576826345DF4",
"0C52B3D11D636E5910A4DD76D32C",
"229E9ECA3053789E937447BC719467075B6138A142DA528DA8F0CF8DDF022FD9AF8E74779BA3AC306609",
"8B7A00038783E8BAF6EDEAE0C4EAB48FC8FD501A588C7E4A4DB71E3604F2155A97687D3D2FFF8569261375A513CF4398CE0F87CA1658A1050F6EF6C4EA3E25",
"C20B6CF8D3C8241825FD90B2EDAC7593600646E579A8D8DAAE9E2E40C3835FE801B2BE4379131452BC5182C90307B176DFBE2049544222FE7783147B690774F6D9D7CEF52A91E61E298E9AA15464AC"},
}

View File

@@ -0,0 +1,78 @@
package ocb
import (
"encoding/hex"
)
// Test vectors from https://tools.ietf.org/html/rfc7253. Note that key is
// shared across tests.
var testKey, _ = hex.DecodeString("000102030405060708090A0B0C0D0E0F")
var rfc7253testVectors = []struct {
nonce, header, plaintext, ciphertext string
}{
{"BBAA99887766554433221100",
"",
"",
"785407BFFFC8AD9EDCC5520AC9111EE6"},
{"BBAA99887766554433221101",
"0001020304050607",
"0001020304050607",
"6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009"},
{"BBAA99887766554433221102",
"0001020304050607",
"",
"81017F8203F081277152FADE694A0A00"},
{"BBAA99887766554433221103",
"",
"0001020304050607",
"45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9"},
{"BBAA99887766554433221104",
"000102030405060708090A0B0C0D0E0F",
"000102030405060708090A0B0C0D0E0F",
"571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358"},
{"BBAA99887766554433221105",
"000102030405060708090A0B0C0D0E0F",
"",
"8CF761B6902EF764462AD86498CA6B97"},
{"BBAA99887766554433221106",
"",
"000102030405060708090A0B0C0D0E0F",
"5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436BDF06D8FA1ECA343D"},
{"BBAA99887766554433221107",
"000102030405060708090A0B0C0D0E0F1011121314151617",
"000102030405060708090A0B0C0D0E0F1011121314151617",
"1CA2207308C87C010756104D8840CE1952F09673A448A122C92C62241051F57356D7F3C90BB0E07F"},
{"BBAA99887766554433221108",
"000102030405060708090A0B0C0D0E0F1011121314151617",
"",
"6DC225A071FC1B9F7C69F93B0F1E10DE"},
{"BBAA99887766554433221109",
"",
"000102030405060708090A0B0C0D0E0F1011121314151617",
"221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3CE725F32494B9F914D85C0B1EB38357FF"},
{"BBAA9988776655443322110A",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
"BD6F6C496201C69296C11EFD138A467ABD3C707924B964DEAFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240"},
{"BBAA9988776655443322110B",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
"",
"FE80690BEE8A485D11F32965BC9D2A32"},
{"BBAA9988776655443322110C",
"",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
"2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF46040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF"},
{"BBAA9988776655443322110D",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
"D5CA91748410C1751FF8A2F618255B68A0A12E093FF454606E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483A7035490C5769E60"},
{"BBAA9988776655443322110E",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
"",
"C5CD9D1850C141E358649994EE701B68"},
{"BBAA9988776655443322110F",
"",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
"4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95A98CA5F3000B1479"},
}

View File

@@ -0,0 +1,25 @@
package ocb
// Second set of test vectors from https://tools.ietf.org/html/rfc7253
var rfc7253TestVectorTaglen96 = struct {
key, nonce, header, plaintext, ciphertext string
}{"0F0E0D0C0B0A09080706050403020100",
"BBAA9988776655443322110D",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
"1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FDAC4F02AA"}
var rfc7253AlgorithmTest = []struct {
KEYLEN, TAGLEN int
OUTPUT string
}{
{128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2"},
{192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17"},
{256, 128, "D90EB8E9C977C88B79DD793D7FFA161C"},
{128, 96, "77A3D8E73589158D25D01209"},
{192, 96, "05D56EAD2752C86BE6932C5E"},
{256, 96, "5458359AC23B0CBA9E6330DD"},
{128, 64, "192C9B7BD90BA06A"},
{192, 64, "0066BC6E0EF34E24"},
{256, 64, "7D4EA5D445501CBE"},
}

View File

@@ -0,0 +1,153 @@
// Copyright 2014 Matthew Endsley
// All rights reserved
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted providing that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// Package keywrap is an implementation of the RFC 3394 AES key wrapping
// algorithm. This is used in OpenPGP with elliptic curve keys.
package keywrap
import (
"crypto/aes"
"encoding/binary"
"errors"
)
var (
// ErrWrapPlaintext is returned if the plaintext is not a multiple
// of 64 bits.
ErrWrapPlaintext = errors.New("keywrap: plainText must be a multiple of 64 bits")
// ErrUnwrapCiphertext is returned if the ciphertext is not a
// multiple of 64 bits.
ErrUnwrapCiphertext = errors.New("keywrap: cipherText must by a multiple of 64 bits")
// ErrUnwrapFailed is returned if unwrapping a key fails.
ErrUnwrapFailed = errors.New("keywrap: failed to unwrap key")
// NB: the AES NewCipher call only fails if the key is an invalid length.
// ErrInvalidKey is returned when the AES key is invalid.
ErrInvalidKey = errors.New("keywrap: invalid AES key")
)
// Wrap a key using the RFC 3394 AES Key Wrap Algorithm.
func Wrap(key, plainText []byte) ([]byte, error) {
if len(plainText)%8 != 0 {
return nil, ErrWrapPlaintext
}
c, err := aes.NewCipher(key)
if err != nil {
return nil, ErrInvalidKey
}
nblocks := len(plainText) / 8
// 1) Initialize variables.
var block [aes.BlockSize]byte
// - Set A = IV, an initial value (see 2.2.3)
for ii := 0; ii < 8; ii++ {
block[ii] = 0xA6
}
// - For i = 1 to n
// - Set R[i] = P[i]
intermediate := make([]byte, len(plainText))
copy(intermediate, plainText)
// 2) Calculate intermediate values.
for ii := 0; ii < 6; ii++ {
for jj := 0; jj < nblocks; jj++ {
// - B = AES(K, A | R[i])
copy(block[8:], intermediate[jj*8:jj*8+8])
c.Encrypt(block[:], block[:])
// - A = MSB(64, B) ^ t where t = (n*j)+1
t := uint64(ii*nblocks + jj + 1)
val := binary.BigEndian.Uint64(block[:8]) ^ t
binary.BigEndian.PutUint64(block[:8], val)
// - R[i] = LSB(64, B)
copy(intermediate[jj*8:jj*8+8], block[8:])
}
}
// 3) Output results.
// - Set C[0] = A
// - For i = 1 to n
// - C[i] = R[i]
return append(block[:8], intermediate...), nil
}
// Unwrap a key using the RFC 3394 AES Key Wrap Algorithm.
func Unwrap(key, cipherText []byte) ([]byte, error) {
if len(cipherText)%8 != 0 {
return nil, ErrUnwrapCiphertext
}
c, err := aes.NewCipher(key)
if err != nil {
return nil, ErrInvalidKey
}
nblocks := len(cipherText)/8 - 1
// 1) Initialize variables.
var block [aes.BlockSize]byte
// - Set A = C[0]
copy(block[:8], cipherText[:8])
// - For i = 1 to n
// - Set R[i] = C[i]
intermediate := make([]byte, len(cipherText)-8)
copy(intermediate, cipherText[8:])
// 2) Compute intermediate values.
for jj := 5; jj >= 0; jj-- {
for ii := nblocks - 1; ii >= 0; ii-- {
// - B = AES-1(K, (A ^ t) | R[i]) where t = n*j+1
// - A = MSB(64, B)
t := uint64(jj*nblocks + ii + 1)
val := binary.BigEndian.Uint64(block[:8]) ^ t
binary.BigEndian.PutUint64(block[:8], val)
copy(block[8:], intermediate[ii*8:ii*8+8])
c.Decrypt(block[:], block[:])
// - R[i] = LSB(B, 64)
copy(intermediate[ii*8:ii*8+8], block[8:])
}
}
// 3) Output results.
// - If A is an appropriate initial value (see 2.2.3),
for ii := 0; ii < 8; ii++ {
if block[ii] != 0xA6 {
return nil, ErrUnwrapFailed
}
}
// - For i = 1 to n
// - P[i] = R[i]
return intermediate, nil
}

View File

@@ -0,0 +1,183 @@
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
// very similar to PEM except that it has an additional CRC checksum.
package armor // import "github.com/ProtonMail/go-crypto/openpgp/armor"
import (
"bufio"
"bytes"
"encoding/base64"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
// A Block represents an OpenPGP armored structure.
//
// The encoded form is:
//
// -----BEGIN Type-----
// Headers
//
// base64-encoded Bytes
// '=' base64 encoded checksum (optional) not checked anymore
// -----END Type-----
//
// where Headers is a possibly empty sequence of Key: Value lines.
//
// Since the armored data can be very large, this package presents a streaming
// interface.
type Block struct {
Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE").
Header map[string]string // Optional headers.
Body io.Reader // A Reader from which the contents can be read
lReader lineReader
oReader openpgpReader
}
var ArmorCorrupt error = errors.StructuralError("armor invalid")
var armorStart = []byte("-----BEGIN ")
var armorEnd = []byte("-----END ")
var armorEndOfLine = []byte("-----")
// lineReader wraps a line based reader. It watches for the end of an armor block
type lineReader struct {
in *bufio.Reader
buf []byte
eof bool
}
func (l *lineReader) Read(p []byte) (n int, err error) {
if l.eof {
return 0, io.EOF
}
if len(l.buf) > 0 {
n = copy(p, l.buf)
l.buf = l.buf[n:]
return
}
line, isPrefix, err := l.in.ReadLine()
if err != nil {
return
}
if isPrefix {
return 0, ArmorCorrupt
}
if bytes.HasPrefix(line, armorEnd) {
l.eof = true
return 0, io.EOF
}
if len(line) == 5 && line[0] == '=' {
// This is the checksum line
// Don't check the checksum
l.eof = true
return 0, io.EOF
}
if len(line) > 96 {
return 0, ArmorCorrupt
}
n = copy(p, line)
bytesToSave := len(line) - n
if bytesToSave > 0 {
if cap(l.buf) < bytesToSave {
l.buf = make([]byte, 0, bytesToSave)
}
l.buf = l.buf[0:bytesToSave]
copy(l.buf, line[n:])
}
return
}
// openpgpReader passes Read calls to the underlying base64 decoder.
type openpgpReader struct {
lReader *lineReader
b64Reader io.Reader
}
func (r *openpgpReader) Read(p []byte) (n int, err error) {
n, err = r.b64Reader.Read(p)
return
}
// Decode reads a PGP armored block from the given Reader. It will ignore
// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The
// given Reader is not usable after calling this function: an arbitrary amount
// of data may have been read past the end of the block.
func Decode(in io.Reader) (p *Block, err error) {
r := bufio.NewReaderSize(in, 100)
var line []byte
ignoreNext := false
TryNextBlock:
p = nil
// Skip leading garbage
for {
ignoreThis := ignoreNext
line, ignoreNext, err = r.ReadLine()
if err != nil {
return
}
if ignoreNext || ignoreThis {
continue
}
line = bytes.TrimSpace(line)
if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) {
break
}
}
p = new(Block)
p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)])
p.Header = make(map[string]string)
nextIsContinuation := false
var lastKey string
// Read headers
for {
isContinuation := nextIsContinuation
line, nextIsContinuation, err = r.ReadLine()
if err != nil {
p = nil
return
}
if isContinuation {
p.Header[lastKey] += string(line)
continue
}
line = bytes.TrimSpace(line)
if len(line) == 0 {
break
}
i := bytes.Index(line, []byte(":"))
if i == -1 {
goto TryNextBlock
}
lastKey = string(line[:i])
var value string
if len(line) > i+2 {
value = string(line[i+2:])
}
p.Header[lastKey] = value
}
p.lReader.in = r
p.oReader.lReader = &p.lReader
p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader)
p.Body = &p.oReader
return
}

View File

@@ -0,0 +1,206 @@
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package armor
import (
"encoding/base64"
"io"
"sort"
)
var armorHeaderSep = []byte(": ")
var blockEnd = []byte("\n=")
var newline = []byte("\n")
var armorEndOfLineOut = []byte("-----\n")
const crc24Init = 0xb704ce
const crc24Poly = 0x1864cfb
// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1
func crc24(crc uint32, d []byte) uint32 {
for _, b := range d {
crc ^= uint32(b) << 16
for i := 0; i < 8; i++ {
crc <<= 1
if crc&0x1000000 != 0 {
crc ^= crc24Poly
}
}
}
return crc
}
// writeSlices writes its arguments to the given Writer.
func writeSlices(out io.Writer, slices ...[]byte) (err error) {
for _, s := range slices {
_, err = out.Write(s)
if err != nil {
return err
}
}
return
}
// lineBreaker breaks data across several lines, all of the same byte length
// (except possibly the last). Lines are broken with a single '\n'.
type lineBreaker struct {
lineLength int
line []byte
used int
out io.Writer
haveWritten bool
}
func newLineBreaker(out io.Writer, lineLength int) *lineBreaker {
return &lineBreaker{
lineLength: lineLength,
line: make([]byte, lineLength),
used: 0,
out: out,
}
}
func (l *lineBreaker) Write(b []byte) (n int, err error) {
n = len(b)
if n == 0 {
return
}
if l.used == 0 && l.haveWritten {
_, err = l.out.Write([]byte{'\n'})
if err != nil {
return
}
}
if l.used+len(b) < l.lineLength {
l.used += copy(l.line[l.used:], b)
return
}
l.haveWritten = true
_, err = l.out.Write(l.line[0:l.used])
if err != nil {
return
}
excess := l.lineLength - l.used
l.used = 0
_, err = l.out.Write(b[0:excess])
if err != nil {
return
}
_, err = l.Write(b[excess:])
return
}
func (l *lineBreaker) Close() (err error) {
if l.used > 0 {
_, err = l.out.Write(l.line[0:l.used])
if err != nil {
return
}
}
return
}
// encoding keeps track of a running CRC24 over the data which has been written
// to it and outputs a OpenPGP checksum when closed, followed by an armor
// trailer.
//
// It's built into a stack of io.Writers:
//
// encoding -> base64 encoder -> lineBreaker -> out
type encoding struct {
out io.Writer
breaker *lineBreaker
b64 io.WriteCloser
crc uint32
crcEnabled bool
blockType []byte
}
func (e *encoding) Write(data []byte) (n int, err error) {
if e.crcEnabled {
e.crc = crc24(e.crc, data)
}
return e.b64.Write(data)
}
func (e *encoding) Close() (err error) {
err = e.b64.Close()
if err != nil {
return
}
e.breaker.Close()
if e.crcEnabled {
var checksumBytes [3]byte
checksumBytes[0] = byte(e.crc >> 16)
checksumBytes[1] = byte(e.crc >> 8)
checksumBytes[2] = byte(e.crc)
var b64ChecksumBytes [4]byte
base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
}
return writeSlices(e.out, newline, armorEnd, e.blockType, armorEndOfLine)
}
func encode(out io.Writer, blockType string, headers map[string]string, checksum bool) (w io.WriteCloser, err error) {
bType := []byte(blockType)
err = writeSlices(out, armorStart, bType, armorEndOfLineOut)
if err != nil {
return
}
keys := make([]string, len(headers))
i := 0
for k := range headers {
keys[i] = k
i++
}
sort.Strings(keys)
for _, k := range keys {
err = writeSlices(out, []byte(k), armorHeaderSep, []byte(headers[k]), newline)
if err != nil {
return
}
}
_, err = out.Write(newline)
if err != nil {
return
}
e := &encoding{
out: out,
breaker: newLineBreaker(out, 64),
blockType: bType,
crc: crc24Init,
crcEnabled: checksum,
}
e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker)
return e, nil
}
// Encode returns a WriteCloser which will encode the data written to it in
// OpenPGP armor.
func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) {
return encode(out, blockType, headers, true)
}
// EncodeWithChecksumOption returns a WriteCloser which will encode the data written to it in
// OpenPGP armor and provides the option to include a checksum.
// When forming ASCII Armor, the CRC24 footer SHOULD NOT be generated,
// unless interoperability with implementations that require the CRC24 footer
// to be present is a concern.
func EncodeWithChecksumOption(out io.Writer, blockType string, headers map[string]string, doChecksum bool) (w io.WriteCloser, err error) {
return encode(out, blockType, headers, doChecksum)
}

View File

@@ -0,0 +1,71 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package openpgp
import (
"hash"
"io"
)
// NewCanonicalTextHash reformats text written to it into the canonical
// form and then applies the hash h. See RFC 4880, section 5.2.1.
func NewCanonicalTextHash(h hash.Hash) hash.Hash {
return &canonicalTextHash{h, 0}
}
type canonicalTextHash struct {
h hash.Hash
s int
}
var newline = []byte{'\r', '\n'}
func writeCanonical(cw io.Writer, buf []byte, s *int) (int, error) {
start := 0
for i, c := range buf {
switch *s {
case 0:
if c == '\r' {
*s = 1
} else if c == '\n' {
if _, err := cw.Write(buf[start:i]); err != nil {
return 0, err
}
if _, err := cw.Write(newline); err != nil {
return 0, err
}
start = i + 1
}
case 1:
*s = 0
}
}
if _, err := cw.Write(buf[start:]); err != nil {
return 0, err
}
return len(buf), nil
}
func (cth *canonicalTextHash) Write(buf []byte) (int, error) {
return writeCanonical(cth.h, buf, &cth.s)
}
func (cth *canonicalTextHash) Sum(in []byte) []byte {
return cth.h.Sum(in)
}
func (cth *canonicalTextHash) Reset() {
cth.h.Reset()
cth.s = 0
}
func (cth *canonicalTextHash) Size() int {
return cth.h.Size()
}
func (cth *canonicalTextHash) BlockSize() int {
return cth.h.BlockSize()
}

View File

@@ -0,0 +1,206 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package ecdh implements ECDH encryption, suitable for OpenPGP,
// as specified in RFC 6637, section 8.
package ecdh
import (
"bytes"
"errors"
"io"
"github.com/ProtonMail/go-crypto/openpgp/aes/keywrap"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
)
type KDF struct {
Hash algorithm.Hash
Cipher algorithm.Cipher
}
type PublicKey struct {
curve ecc.ECDHCurve
Point []byte
KDF
}
type PrivateKey struct {
PublicKey
D []byte
}
func NewPublicKey(curve ecc.ECDHCurve, kdfHash algorithm.Hash, kdfCipher algorithm.Cipher) *PublicKey {
return &PublicKey{
curve: curve,
KDF: KDF{
Hash: kdfHash,
Cipher: kdfCipher,
},
}
}
func NewPrivateKey(key PublicKey) *PrivateKey {
return &PrivateKey{
PublicKey: key,
}
}
func (pk *PublicKey) GetCurve() ecc.ECDHCurve {
return pk.curve
}
func (pk *PublicKey) MarshalPoint() []byte {
return pk.curve.MarshalBytePoint(pk.Point)
}
func (pk *PublicKey) UnmarshalPoint(p []byte) error {
pk.Point = pk.curve.UnmarshalBytePoint(p)
if pk.Point == nil {
return errors.New("ecdh: failed to parse EC point")
}
return nil
}
func (sk *PrivateKey) MarshalByteSecret() []byte {
return sk.curve.MarshalByteSecret(sk.D)
}
func (sk *PrivateKey) UnmarshalByteSecret(d []byte) error {
sk.D = sk.curve.UnmarshalByteSecret(d)
if sk.D == nil {
return errors.New("ecdh: failed to parse scalar")
}
return nil
}
func GenerateKey(rand io.Reader, c ecc.ECDHCurve, kdf KDF) (priv *PrivateKey, err error) {
priv = new(PrivateKey)
priv.PublicKey.curve = c
priv.PublicKey.KDF = kdf
priv.PublicKey.Point, priv.D, err = c.GenerateECDH(rand)
return
}
func Encrypt(random io.Reader, pub *PublicKey, msg, curveOID, fingerprint []byte) (vsG, c []byte, err error) {
if len(msg) > 40 {
return nil, nil, errors.New("ecdh: message too long")
}
// the sender MAY use 21, 13, and 5 bytes of padding for AES-128,
// AES-192, and AES-256, respectively, to provide the same number of
// octets, 40 total, as an input to the key wrapping method.
padding := make([]byte, 40-len(msg))
for i := range padding {
padding[i] = byte(40 - len(msg))
}
m := append(msg, padding...)
ephemeral, zb, err := pub.curve.Encaps(random, pub.Point)
if err != nil {
return nil, nil, err
}
vsG = pub.curve.MarshalBytePoint(ephemeral)
z, err := buildKey(pub, zb, curveOID, fingerprint, false, false)
if err != nil {
return nil, nil, err
}
if c, err = keywrap.Wrap(z, m); err != nil {
return nil, nil, err
}
return vsG, c, nil
}
func Decrypt(priv *PrivateKey, vsG, c, curveOID, fingerprint []byte) (msg []byte, err error) {
var m []byte
zb, err := priv.PublicKey.curve.Decaps(priv.curve.UnmarshalBytePoint(vsG), priv.D)
// Try buildKey three times to workaround an old bug, see comments in buildKey.
for i := 0; i < 3; i++ {
var z []byte
// RFC6637 §8: "Compute Z = KDF( S, Z_len, Param );"
z, err = buildKey(&priv.PublicKey, zb, curveOID, fingerprint, i == 1, i == 2)
if err != nil {
return nil, err
}
// RFC6637 §8: "Compute C = AESKeyWrap( Z, c ) as per [RFC3394]"
m, err = keywrap.Unwrap(z, c)
if err == nil {
break
}
}
// Only return an error after we've tried all (required) variants of buildKey.
if err != nil {
return nil, err
}
// RFC6637 §8: "m = symm_alg_ID || session key || checksum || pkcs5_padding"
// The last byte should be the length of the padding, as per PKCS5; strip it off.
return m[:len(m)-int(m[len(m)-1])], nil
}
func buildKey(pub *PublicKey, zb []byte, curveOID, fingerprint []byte, stripLeading, stripTrailing bool) ([]byte, error) {
// Param = curve_OID_len || curve_OID || public_key_alg_ID || 03
// || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap
// || "Anonymous Sender " || recipient_fingerprint;
param := new(bytes.Buffer)
if _, err := param.Write(curveOID); err != nil {
return nil, err
}
algKDF := []byte{18, 3, 1, pub.KDF.Hash.Id(), pub.KDF.Cipher.Id()}
if _, err := param.Write(algKDF); err != nil {
return nil, err
}
if _, err := param.Write([]byte("Anonymous Sender ")); err != nil {
return nil, err
}
if _, err := param.Write(fingerprint[:]); err != nil {
return nil, err
}
// MB = Hash ( 00 || 00 || 00 || 01 || ZB || Param );
h := pub.KDF.Hash.New()
if _, err := h.Write([]byte{0x0, 0x0, 0x0, 0x1}); err != nil {
return nil, err
}
zbLen := len(zb)
i := 0
j := zbLen - 1
if stripLeading {
// Work around old go crypto bug where the leading zeros are missing.
for i < zbLen && zb[i] == 0 {
i++
}
}
if stripTrailing {
// Work around old OpenPGP.js bug where insignificant trailing zeros in
// this little-endian number are missing.
// (See https://github.com/openpgpjs/openpgpjs/pull/853.)
for j >= 0 && zb[j] == 0 {
j--
}
}
if _, err := h.Write(zb[i : j+1]); err != nil {
return nil, err
}
if _, err := h.Write(param.Bytes()); err != nil {
return nil, err
}
mb := h.Sum(nil)
return mb[:pub.KDF.Cipher.KeySize()], nil // return oBits leftmost bits of MB.
}
func Validate(priv *PrivateKey) error {
return priv.curve.ValidateECDH(priv.Point, priv.D)
}

View File

@@ -0,0 +1,80 @@
// Package ecdsa implements ECDSA signature, suitable for OpenPGP,
// as specified in RFC 6637, section 5.
package ecdsa
import (
"errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
"io"
"math/big"
)
type PublicKey struct {
X, Y *big.Int
curve ecc.ECDSACurve
}
type PrivateKey struct {
PublicKey
D *big.Int
}
func NewPublicKey(curve ecc.ECDSACurve) *PublicKey {
return &PublicKey{
curve: curve,
}
}
func NewPrivateKey(key PublicKey) *PrivateKey {
return &PrivateKey{
PublicKey: key,
}
}
func (pk *PublicKey) GetCurve() ecc.ECDSACurve {
return pk.curve
}
func (pk *PublicKey) MarshalPoint() []byte {
return pk.curve.MarshalIntegerPoint(pk.X, pk.Y)
}
func (pk *PublicKey) UnmarshalPoint(p []byte) error {
pk.X, pk.Y = pk.curve.UnmarshalIntegerPoint(p)
if pk.X == nil {
return errors.New("ecdsa: failed to parse EC point")
}
return nil
}
func (sk *PrivateKey) MarshalIntegerSecret() []byte {
return sk.curve.MarshalIntegerSecret(sk.D)
}
func (sk *PrivateKey) UnmarshalIntegerSecret(d []byte) error {
sk.D = sk.curve.UnmarshalIntegerSecret(d)
if sk.D == nil {
return errors.New("ecdsa: failed to parse scalar")
}
return nil
}
func GenerateKey(rand io.Reader, c ecc.ECDSACurve) (priv *PrivateKey, err error) {
priv = new(PrivateKey)
priv.PublicKey.curve = c
priv.PublicKey.X, priv.PublicKey.Y, priv.D, err = c.GenerateECDSA(rand)
return
}
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
return priv.PublicKey.curve.Sign(rand, priv.X, priv.Y, priv.D, hash)
}
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
return pub.curve.Verify(pub.X, pub.Y, hash, r, s)
}
func Validate(priv *PrivateKey) error {
return priv.curve.ValidateECDSA(priv.X, priv.Y, priv.D.Bytes())
}

View File

@@ -0,0 +1,115 @@
// Package ed25519 implements the ed25519 signature algorithm for OpenPGP
// as defined in the Open PGP crypto refresh.
package ed25519
import (
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
ed25519lib "github.com/cloudflare/circl/sign/ed25519"
)
const (
// PublicKeySize is the size, in bytes, of public keys in this package.
PublicKeySize = ed25519lib.PublicKeySize
// SeedSize is the size, in bytes, of private key seeds.
// The private key representation used by RFC 8032.
SeedSize = ed25519lib.SeedSize
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = ed25519lib.SignatureSize
)
type PublicKey struct {
// Point represents the elliptic curve point of the public key.
Point []byte
}
type PrivateKey struct {
PublicKey
// Key the private key representation by RFC 8032,
// encoded as seed | pub key point.
Key []byte
}
// NewPublicKey creates a new empty ed25519 public key.
func NewPublicKey() *PublicKey {
return &PublicKey{}
}
// NewPrivateKey creates a new empty private key referencing the public key.
func NewPrivateKey(key PublicKey) *PrivateKey {
return &PrivateKey{
PublicKey: key,
}
}
// Seed returns the ed25519 private key secret seed.
// The private key representation by RFC 8032.
func (pk *PrivateKey) Seed() []byte {
return pk.Key[:SeedSize]
}
// MarshalByteSecret returns the underlying 32 byte seed of the private key.
func (pk *PrivateKey) MarshalByteSecret() []byte {
return pk.Seed()
}
// UnmarshalByteSecret computes the private key from the secret seed
// and stores it in the private key object.
func (sk *PrivateKey) UnmarshalByteSecret(seed []byte) error {
sk.Key = ed25519lib.NewKeyFromSeed(seed)
return nil
}
// GenerateKey generates a fresh private key with the provided randomness source.
func GenerateKey(rand io.Reader) (*PrivateKey, error) {
publicKey, privateKey, err := ed25519lib.GenerateKey(rand)
if err != nil {
return nil, err
}
privateKeyOut := new(PrivateKey)
privateKeyOut.PublicKey.Point = publicKey[:]
privateKeyOut.Key = privateKey[:]
return privateKeyOut, nil
}
// Sign signs a message with the ed25519 algorithm.
// priv MUST be a valid key! Check this with Validate() before use.
func Sign(priv *PrivateKey, message []byte) ([]byte, error) {
return ed25519lib.Sign(priv.Key, message), nil
}
// Verify verifies an ed25519 signature.
func Verify(pub *PublicKey, message []byte, signature []byte) bool {
return ed25519lib.Verify(pub.Point, message, signature)
}
// Validate checks if the ed25519 private key is valid.
func Validate(priv *PrivateKey) error {
expectedPrivateKey := ed25519lib.NewKeyFromSeed(priv.Seed())
if subtle.ConstantTimeCompare(priv.Key, expectedPrivateKey) == 0 {
return errors.KeyInvalidError("ed25519: invalid ed25519 secret")
}
if subtle.ConstantTimeCompare(priv.PublicKey.Point, expectedPrivateKey[SeedSize:]) == 0 {
return errors.KeyInvalidError("ed25519: invalid ed25519 public key")
}
return nil
}
// ENCODING/DECODING signature:
// WriteSignature encodes and writes an ed25519 signature to writer.
func WriteSignature(writer io.Writer, signature []byte) error {
_, err := writer.Write(signature)
return err
}
// ReadSignature decodes an ed25519 signature from a reader.
func ReadSignature(reader io.Reader) ([]byte, error) {
signature := make([]byte, SignatureSize)
if _, err := io.ReadFull(reader, signature); err != nil {
return nil, err
}
return signature, nil
}

View File

@@ -0,0 +1,119 @@
// Package ed448 implements the ed448 signature algorithm for OpenPGP
// as defined in the Open PGP crypto refresh.
package ed448
import (
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
ed448lib "github.com/cloudflare/circl/sign/ed448"
)
const (
// PublicKeySize is the size, in bytes, of public keys in this package.
PublicKeySize = ed448lib.PublicKeySize
// SeedSize is the size, in bytes, of private key seeds.
// The private key representation used by RFC 8032.
SeedSize = ed448lib.SeedSize
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = ed448lib.SignatureSize
)
type PublicKey struct {
// Point represents the elliptic curve point of the public key.
Point []byte
}
type PrivateKey struct {
PublicKey
// Key the private key representation by RFC 8032,
// encoded as seed | public key point.
Key []byte
}
// NewPublicKey creates a new empty ed448 public key.
func NewPublicKey() *PublicKey {
return &PublicKey{}
}
// NewPrivateKey creates a new empty private key referencing the public key.
func NewPrivateKey(key PublicKey) *PrivateKey {
return &PrivateKey{
PublicKey: key,
}
}
// Seed returns the ed448 private key secret seed.
// The private key representation by RFC 8032.
func (pk *PrivateKey) Seed() []byte {
return pk.Key[:SeedSize]
}
// MarshalByteSecret returns the underlying seed of the private key.
func (pk *PrivateKey) MarshalByteSecret() []byte {
return pk.Seed()
}
// UnmarshalByteSecret computes the private key from the secret seed
// and stores it in the private key object.
func (sk *PrivateKey) UnmarshalByteSecret(seed []byte) error {
sk.Key = ed448lib.NewKeyFromSeed(seed)
return nil
}
// GenerateKey generates a fresh private key with the provided randomness source.
func GenerateKey(rand io.Reader) (*PrivateKey, error) {
publicKey, privateKey, err := ed448lib.GenerateKey(rand)
if err != nil {
return nil, err
}
privateKeyOut := new(PrivateKey)
privateKeyOut.PublicKey.Point = publicKey[:]
privateKeyOut.Key = privateKey[:]
return privateKeyOut, nil
}
// Sign signs a message with the ed448 algorithm.
// priv MUST be a valid key! Check this with Validate() before use.
func Sign(priv *PrivateKey, message []byte) ([]byte, error) {
// Ed448 is used with the empty string as a context string.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-08#section-13.7
return ed448lib.Sign(priv.Key, message, ""), nil
}
// Verify verifies a ed448 signature
func Verify(pub *PublicKey, message []byte, signature []byte) bool {
// Ed448 is used with the empty string as a context string.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-08#section-13.7
return ed448lib.Verify(pub.Point, message, signature, "")
}
// Validate checks if the ed448 private key is valid
func Validate(priv *PrivateKey) error {
expectedPrivateKey := ed448lib.NewKeyFromSeed(priv.Seed())
if subtle.ConstantTimeCompare(priv.Key, expectedPrivateKey) == 0 {
return errors.KeyInvalidError("ed448: invalid ed448 secret")
}
if subtle.ConstantTimeCompare(priv.PublicKey.Point, expectedPrivateKey[SeedSize:]) == 0 {
return errors.KeyInvalidError("ed448: invalid ed448 public key")
}
return nil
}
// ENCODING/DECODING signature:
// WriteSignature encodes and writes an ed448 signature to writer.
func WriteSignature(writer io.Writer, signature []byte) error {
_, err := writer.Write(signature)
return err
}
// ReadSignature decodes an ed448 signature from a reader.
func ReadSignature(reader io.Reader) ([]byte, error) {
signature := make([]byte, SignatureSize)
if _, err := io.ReadFull(reader, signature); err != nil {
return nil, err
}
return signature, nil
}

View File

@@ -0,0 +1,91 @@
// Package eddsa implements EdDSA signature, suitable for OpenPGP, as specified in
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7
package eddsa
import (
"errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
"io"
)
type PublicKey struct {
X []byte
curve ecc.EdDSACurve
}
type PrivateKey struct {
PublicKey
D []byte
}
func NewPublicKey(curve ecc.EdDSACurve) *PublicKey {
return &PublicKey{
curve: curve,
}
}
func NewPrivateKey(key PublicKey) *PrivateKey {
return &PrivateKey{
PublicKey: key,
}
}
func (pk *PublicKey) GetCurve() ecc.EdDSACurve {
return pk.curve
}
func (pk *PublicKey) MarshalPoint() []byte {
return pk.curve.MarshalBytePoint(pk.X)
}
func (pk *PublicKey) UnmarshalPoint(x []byte) error {
pk.X = pk.curve.UnmarshalBytePoint(x)
if pk.X == nil {
return errors.New("eddsa: failed to parse EC point")
}
return nil
}
func (sk *PrivateKey) MarshalByteSecret() []byte {
return sk.curve.MarshalByteSecret(sk.D)
}
func (sk *PrivateKey) UnmarshalByteSecret(d []byte) error {
sk.D = sk.curve.UnmarshalByteSecret(d)
if sk.D == nil {
return errors.New("eddsa: failed to parse scalar")
}
return nil
}
func GenerateKey(rand io.Reader, c ecc.EdDSACurve) (priv *PrivateKey, err error) {
priv = new(PrivateKey)
priv.PublicKey.curve = c
priv.PublicKey.X, priv.D, err = c.GenerateEdDSA(rand)
return
}
func Sign(priv *PrivateKey, message []byte) (r, s []byte, err error) {
sig, err := priv.PublicKey.curve.Sign(priv.PublicKey.X, priv.D, message)
if err != nil {
return nil, nil, err
}
r, s = priv.PublicKey.curve.MarshalSignature(sig)
return
}
func Verify(pub *PublicKey, message, r, s []byte) bool {
sig := pub.curve.UnmarshalSignature(r, s)
if sig == nil {
return false
}
return pub.curve.Verify(pub.X, message, sig)
}
func Validate(priv *PrivateKey) error {
return priv.curve.ValidateEdDSA(priv.PublicKey.X, priv.D)
}

View File

@@ -0,0 +1,124 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package elgamal implements ElGamal encryption, suitable for OpenPGP,
// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on
// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31,
// n. 4, 1985, pp. 469-472.
//
// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it
// unsuitable for other protocols. RSA should be used in preference in any
// case.
package elgamal // import "github.com/ProtonMail/go-crypto/openpgp/elgamal"
import (
"crypto/rand"
"crypto/subtle"
"errors"
"io"
"math/big"
)
// PublicKey represents an ElGamal public key.
type PublicKey struct {
G, P, Y *big.Int
}
// PrivateKey represents an ElGamal private key.
type PrivateKey struct {
PublicKey
X *big.Int
}
// Encrypt encrypts the given message to the given public key. The result is a
// pair of integers. Errors can result from reading random, or because msg is
// too large to be encrypted to the public key.
func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) {
pLen := (pub.P.BitLen() + 7) / 8
if len(msg) > pLen-11 {
err = errors.New("elgamal: message too long")
return
}
// EM = 0x02 || PS || 0x00 || M
em := make([]byte, pLen-1)
em[0] = 2
ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
err = nonZeroRandomBytes(ps, random)
if err != nil {
return
}
em[len(em)-len(msg)-1] = 0
copy(mm, msg)
m := new(big.Int).SetBytes(em)
k, err := rand.Int(random, pub.P)
if err != nil {
return
}
c1 = new(big.Int).Exp(pub.G, k, pub.P)
s := new(big.Int).Exp(pub.Y, k, pub.P)
c2 = s.Mul(s, m)
c2.Mod(c2, pub.P)
return
}
// Decrypt takes two integers, resulting from an ElGamal encryption, and
// returns the plaintext of the message. An error can result only if the
// ciphertext is invalid. Users should keep in mind that this is a padding
// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can
// be used to break the cryptosystem. See “Chosen Ciphertext Attacks
// Against Protocols Based on the RSA Encryption Standard PKCS #1”, Daniel
// Bleichenbacher, Advances in Cryptology (Crypto '98),
func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
s := new(big.Int).Exp(c1, priv.X, priv.P)
if s.ModInverse(s, priv.P) == nil {
return nil, errors.New("elgamal: invalid private key")
}
s.Mul(s, c2)
s.Mod(s, priv.P)
em := s.Bytes()
firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2)
// The remainder of the plaintext must be a string of non-zero random
// octets, followed by a 0, followed by the message.
// lookingForIndex: 1 iff we are still looking for the zero.
// index: the offset of the first zero byte.
var lookingForIndex, index int
lookingForIndex = 1
for i := 1; i < len(em); i++ {
equals0 := subtle.ConstantTimeByteEq(em[i], 0)
index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
}
if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 {
return nil, errors.New("elgamal: decryption error")
}
return em[index+1:], nil
}
// nonZeroRandomBytes fills the given slice with non-zero random octets.
func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
_, err = io.ReadFull(rand, s)
if err != nil {
return
}
for i := 0; i < len(s); i++ {
for s[i] == 0 {
_, err = io.ReadFull(rand, s[i:i+1])
if err != nil {
return
}
}
}
return
}

View File

@@ -0,0 +1,210 @@
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package errors contains common error types for the OpenPGP packages.
package errors // import "github.com/ProtonMail/go-crypto/openpgp/errors"
import (
"fmt"
"strconv"
)
var (
// ErrDecryptSessionKeyParsing is a generic error message for parsing errors in decrypted data
// to reduce the risk of oracle attacks.
ErrDecryptSessionKeyParsing = DecryptWithSessionKeyError("parsing error")
// ErrAEADTagVerification is returned if one of the tag verifications in SEIPDv2 fails
ErrAEADTagVerification error = DecryptWithSessionKeyError("AEAD tag verification failed")
// ErrMDCHashMismatch
ErrMDCHashMismatch error = SignatureError("MDC hash mismatch")
// ErrMDCMissing
ErrMDCMissing error = SignatureError("MDC packet not found")
)
// A StructuralError is returned when OpenPGP data is found to be syntactically
// invalid.
type StructuralError string
func (s StructuralError) Error() string {
return "openpgp: invalid data: " + string(s)
}
// A DecryptWithSessionKeyError is returned when a failure occurs when reading from symmetrically decrypted data or
// an authentication tag verification fails.
// Such an error indicates that the supplied session key is likely wrong or the data got corrupted.
type DecryptWithSessionKeyError string
func (s DecryptWithSessionKeyError) Error() string {
return "openpgp: decryption with session key failed: " + string(s)
}
// HandleSensitiveParsingError handles parsing errors when reading data from potentially decrypted data.
// The function makes parsing errors generic to reduce the risk of oracle attacks in SEIPDv1.
func HandleSensitiveParsingError(err error, decrypted bool) error {
if !decrypted {
// Data was not encrypted so we return the inner error.
return err
}
// The data is read from a stream that decrypts using a session key;
// therefore, we need to handle parsing errors appropriately.
// This is essential to mitigate the risk of oracle attacks.
if decError, ok := err.(*DecryptWithSessionKeyError); ok {
return decError
}
if decError, ok := err.(DecryptWithSessionKeyError); ok {
return decError
}
return ErrDecryptSessionKeyParsing
}
// UnsupportedError indicates that, although the OpenPGP data is valid, it
// makes use of currently unimplemented features.
type UnsupportedError string
func (s UnsupportedError) Error() string {
return "openpgp: unsupported feature: " + string(s)
}
// InvalidArgumentError indicates that the caller is in error and passed an
// incorrect value.
type InvalidArgumentError string
func (i InvalidArgumentError) Error() string {
return "openpgp: invalid argument: " + string(i)
}
// SignatureError indicates that a syntactically valid signature failed to
// validate.
type SignatureError string
func (b SignatureError) Error() string {
return "openpgp: invalid signature: " + string(b)
}
type signatureExpiredError int
func (se signatureExpiredError) Error() string {
return "openpgp: signature expired"
}
var ErrSignatureExpired error = signatureExpiredError(0)
type keyExpiredError int
func (ke keyExpiredError) Error() string {
return "openpgp: key expired"
}
var ErrSignatureOlderThanKey error = signatureOlderThanKeyError(0)
type signatureOlderThanKeyError int
func (ske signatureOlderThanKeyError) Error() string {
return "openpgp: signature is older than the key"
}
var ErrKeyExpired error = keyExpiredError(0)
type keyIncorrectError int
func (ki keyIncorrectError) Error() string {
return "openpgp: incorrect key"
}
var ErrKeyIncorrect error = keyIncorrectError(0)
// KeyInvalidError indicates that the public key parameters are invalid
// as they do not match the private ones
type KeyInvalidError string
func (e KeyInvalidError) Error() string {
return "openpgp: invalid key: " + string(e)
}
type unknownIssuerError int
func (unknownIssuerError) Error() string {
return "openpgp: signature made by unknown entity"
}
var ErrUnknownIssuer error = unknownIssuerError(0)
type keyRevokedError int
func (keyRevokedError) Error() string {
return "openpgp: signature made by revoked key"
}
var ErrKeyRevoked error = keyRevokedError(0)
type WeakAlgorithmError string
func (e WeakAlgorithmError) Error() string {
return "openpgp: weak algorithms are rejected: " + string(e)
}
type UnknownPacketTypeError uint8
func (upte UnknownPacketTypeError) Error() string {
return "openpgp: unknown packet type: " + strconv.Itoa(int(upte))
}
type CriticalUnknownPacketTypeError uint8
func (upte CriticalUnknownPacketTypeError) Error() string {
return "openpgp: unknown critical packet type: " + strconv.Itoa(int(upte))
}
// AEADError indicates that there is a problem when initializing or using a
// AEAD instance, configuration struct, nonces or index values.
type AEADError string
func (ae AEADError) Error() string {
return "openpgp: aead error: " + string(ae)
}
// ErrDummyPrivateKey results when operations are attempted on a private key
// that is just a dummy key. See
// https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=fe55ae16ab4e26d8356dc574c9e8bc935e71aef1;hb=23191d7851eae2217ecdac6484349849a24fd94a#l1109
type ErrDummyPrivateKey string
func (dke ErrDummyPrivateKey) Error() string {
return "openpgp: s2k GNU dummy key: " + string(dke)
}
// ErrMalformedMessage results when the packet sequence is incorrect
type ErrMalformedMessage string
func (dke ErrMalformedMessage) Error() string {
return "openpgp: malformed message " + string(dke)
}
type messageTooLargeError int
func (e messageTooLargeError) Error() string {
return "openpgp: decompressed message size exceeds provided limit"
}
// ErrMessageTooLarge is returned if the read data from
// a compressed packet exceeds the provided limit.
var ErrMessageTooLarge error = messageTooLargeError(0)
// ErrEncryptionKeySelection is returned if encryption key selection fails (v2 API).
type ErrEncryptionKeySelection struct {
PrimaryKeyId string
PrimaryKeyErr error
EncSelectionKeyId *string
EncSelectionErr error
}
func (eks ErrEncryptionKeySelection) Error() string {
prefix := fmt.Sprintf("openpgp: key selection for primary key %s:", eks.PrimaryKeyId)
if eks.PrimaryKeyErr != nil {
return fmt.Sprintf("%s invalid primary key: %s", prefix, eks.PrimaryKeyErr)
}
if eks.EncSelectionKeyId != nil {
return fmt.Sprintf("%s invalid encryption key %s: %s", prefix, *eks.EncSelectionKeyId, eks.EncSelectionErr)
}
return fmt.Sprintf("%s no encryption key: %s", prefix, eks.EncSelectionErr)
}

24
vendor/github.com/ProtonMail/go-crypto/openpgp/hash.go generated vendored Normal file
View File

@@ -0,0 +1,24 @@
package openpgp
import (
"crypto"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
)
// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
// hash id.
func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
return algorithm.HashIdToHash(id)
}
// HashIdToString returns the name of the hash function corresponding to the
// given OpenPGP hash id.
func HashIdToString(id byte) (name string, ok bool) {
return algorithm.HashIdToString(id)
}
// HashToHashId returns an OpenPGP hash id which corresponds the given Hash.
func HashToHashId(h crypto.Hash) (id byte, ok bool) {
return algorithm.HashToHashId(h)
}

View File

@@ -0,0 +1,65 @@
// Copyright (C) 2019 ProtonTech AG
package algorithm
import (
"crypto/cipher"
"github.com/ProtonMail/go-crypto/eax"
"github.com/ProtonMail/go-crypto/ocb"
)
// AEADMode defines the Authenticated Encryption with Associated Data mode of
// operation.
type AEADMode uint8
// Supported modes of operation (see RFC4880bis [EAX] and RFC7253)
const (
AEADModeEAX = AEADMode(1)
AEADModeOCB = AEADMode(2)
AEADModeGCM = AEADMode(3)
)
// TagLength returns the length in bytes of authentication tags.
func (mode AEADMode) TagLength() int {
switch mode {
case AEADModeEAX:
return 16
case AEADModeOCB:
return 16
case AEADModeGCM:
return 16
default:
return 0
}
}
// NonceLength returns the length in bytes of nonces.
func (mode AEADMode) NonceLength() int {
switch mode {
case AEADModeEAX:
return 16
case AEADModeOCB:
return 15
case AEADModeGCM:
return 12
default:
return 0
}
}
// New returns a fresh instance of the given mode
func (mode AEADMode) New(block cipher.Block) (alg cipher.AEAD) {
var err error
switch mode {
case AEADModeEAX:
alg, err = eax.NewEAX(block)
case AEADModeOCB:
alg, err = ocb.NewOCB(block)
case AEADModeGCM:
alg, err = cipher.NewGCM(block)
}
if err != nil {
panic(err.Error())
}
return alg
}

View File

@@ -0,0 +1,97 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package algorithm
import (
"crypto/aes"
"crypto/cipher"
"crypto/des"
"golang.org/x/crypto/cast5"
)
// Cipher is an official symmetric key cipher algorithm. See RFC 4880,
// section 9.2.
type Cipher interface {
// Id returns the algorithm ID, as a byte, of the cipher.
Id() uint8
// KeySize returns the key size, in bytes, of the cipher.
KeySize() int
// BlockSize returns the block size, in bytes, of the cipher.
BlockSize() int
// New returns a fresh instance of the given cipher.
New(key []byte) cipher.Block
}
// The following constants mirror the OpenPGP standard (RFC 4880).
const (
TripleDES = CipherFunction(2)
CAST5 = CipherFunction(3)
AES128 = CipherFunction(7)
AES192 = CipherFunction(8)
AES256 = CipherFunction(9)
)
// CipherById represents the different block ciphers specified for OpenPGP. See
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
var CipherById = map[uint8]Cipher{
TripleDES.Id(): TripleDES,
CAST5.Id(): CAST5,
AES128.Id(): AES128,
AES192.Id(): AES192,
AES256.Id(): AES256,
}
type CipherFunction uint8
// ID returns the algorithm Id, as a byte, of cipher.
func (sk CipherFunction) Id() uint8 {
return uint8(sk)
}
// KeySize returns the key size, in bytes, of cipher.
func (cipher CipherFunction) KeySize() int {
switch cipher {
case CAST5:
return cast5.KeySize
case AES128:
return 16
case AES192, TripleDES:
return 24
case AES256:
return 32
}
return 0
}
// BlockSize returns the block size, in bytes, of cipher.
func (cipher CipherFunction) BlockSize() int {
switch cipher {
case TripleDES:
return des.BlockSize
case CAST5:
return 8
case AES128, AES192, AES256:
return 16
}
return 0
}
// New returns a fresh instance of the given cipher.
func (cipher CipherFunction) New(key []byte) (block cipher.Block) {
var err error
switch cipher {
case TripleDES:
block, err = des.NewTripleDESCipher(key)
case CAST5:
block, err = cast5.NewCipher(key)
case AES128, AES192, AES256:
block, err = aes.NewCipher(key)
}
if err != nil {
panic(err.Error())
}
return
}

View File

@@ -0,0 +1,143 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package algorithm
import (
"crypto"
"fmt"
"hash"
)
// Hash is an official hash function algorithm. See RFC 4880, section 9.4.
type Hash interface {
// Id returns the algorithm ID, as a byte, of Hash.
Id() uint8
// Available reports whether the given hash function is linked into the binary.
Available() bool
// HashFunc simply returns the value of h so that Hash implements SignerOpts.
HashFunc() crypto.Hash
// New returns a new hash.Hash calculating the given hash function. New
// panics if the hash function is not linked into the binary.
New() hash.Hash
// Size returns the length, in bytes, of a digest resulting from the given
// hash function. It doesn't require that the hash function in question be
// linked into the program.
Size() int
// String is the name of the hash function corresponding to the given
// OpenPGP hash id.
String() string
}
// The following vars mirror the crypto/Hash supported hash functions.
var (
SHA1 Hash = cryptoHash{2, crypto.SHA1}
SHA256 Hash = cryptoHash{8, crypto.SHA256}
SHA384 Hash = cryptoHash{9, crypto.SHA384}
SHA512 Hash = cryptoHash{10, crypto.SHA512}
SHA224 Hash = cryptoHash{11, crypto.SHA224}
SHA3_256 Hash = cryptoHash{12, crypto.SHA3_256}
SHA3_512 Hash = cryptoHash{14, crypto.SHA3_512}
)
// HashById represents the different hash functions specified for OpenPGP. See
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-14
var (
HashById = map[uint8]Hash{
SHA256.Id(): SHA256,
SHA384.Id(): SHA384,
SHA512.Id(): SHA512,
SHA224.Id(): SHA224,
SHA3_256.Id(): SHA3_256,
SHA3_512.Id(): SHA3_512,
}
)
// cryptoHash contains pairs relating OpenPGP's hash identifier with
// Go's crypto.Hash type. See RFC 4880, section 9.4.
type cryptoHash struct {
id uint8
crypto.Hash
}
// Id returns the algorithm ID, as a byte, of cryptoHash.
func (h cryptoHash) Id() uint8 {
return h.id
}
var hashNames = map[uint8]string{
SHA256.Id(): "SHA256",
SHA384.Id(): "SHA384",
SHA512.Id(): "SHA512",
SHA224.Id(): "SHA224",
SHA3_256.Id(): "SHA3-256",
SHA3_512.Id(): "SHA3-512",
}
func (h cryptoHash) String() string {
s, ok := hashNames[h.id]
if !ok {
panic(fmt.Sprintf("Unsupported hash function %d", h.id))
}
return s
}
// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
// hash id.
func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
if hash, ok := HashById[id]; ok {
return hash.HashFunc(), true
}
return 0, false
}
// HashIdToHashWithSha1 returns a crypto.Hash which corresponds to the given OpenPGP
// hash id, allowing sha1.
func HashIdToHashWithSha1(id byte) (h crypto.Hash, ok bool) {
if hash, ok := HashById[id]; ok {
return hash.HashFunc(), true
}
if id == SHA1.Id() {
return SHA1.HashFunc(), true
}
return 0, false
}
// HashIdToString returns the name of the hash function corresponding to the
// given OpenPGP hash id.
func HashIdToString(id byte) (name string, ok bool) {
if hash, ok := HashById[id]; ok {
return hash.String(), true
}
return "", false
}
// HashToHashId returns an OpenPGP hash id which corresponds the given Hash.
func HashToHashId(h crypto.Hash) (id byte, ok bool) {
for id, hash := range HashById {
if hash.HashFunc() == h {
return id, true
}
}
return 0, false
}
// HashToHashIdWithSha1 returns an OpenPGP hash id which corresponds the given Hash,
// allowing instances of SHA1
func HashToHashIdWithSha1(h crypto.Hash) (id byte, ok bool) {
for id, hash := range HashById {
if hash.HashFunc() == h {
return id, true
}
}
if h == SHA1.HashFunc() {
return SHA1.Id(), true
}
return 0, false
}

View File

@@ -0,0 +1,171 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
x25519lib "github.com/cloudflare/circl/dh/x25519"
)
type curve25519 struct{}
func NewCurve25519() *curve25519 {
return &curve25519{}
}
func (c *curve25519) GetCurveName() string {
return "curve25519"
}
// MarshalBytePoint encodes the public point from native format, adding the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
func (c *curve25519) MarshalBytePoint(point []byte) []byte {
return append([]byte{0x40}, point...)
}
// UnmarshalBytePoint decodes the public point to native format, removing the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
func (c *curve25519) UnmarshalBytePoint(point []byte) []byte {
if len(point) != x25519lib.Size+1 {
return nil
}
// Remove prefix
return point[1:]
}
// MarshalByteSecret encodes the secret scalar from native format.
// Note that the EC secret scalar differs from the definition of public keys in
// [Curve25519] in two ways: (1) the byte-ordering is big-endian, which is
// more uniform with how big integers are represented in OpenPGP, and (2) the
// leading zeros are truncated.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.1
// Note that leading zero bytes are stripped later when encoding as an MPI.
func (c *curve25519) MarshalByteSecret(secret []byte) []byte {
d := make([]byte, x25519lib.Size)
copyReversed(d, secret)
// The following ensures that the private key is a number of the form
// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of
// the curve.
//
// This masking is done internally in the underlying lib and so is unnecessary
// for security, but OpenPGP implementations require that private keys be
// pre-masked.
d[0] &= 127
d[0] |= 64
d[31] &= 248
return d
}
// UnmarshalByteSecret decodes the secret scalar from native format.
// Note that the EC secret scalar differs from the definition of public keys in
// [Curve25519] in two ways: (1) the byte-ordering is big-endian, which is
// more uniform with how big integers are represented in OpenPGP, and (2) the
// leading zeros are truncated.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.1
func (c *curve25519) UnmarshalByteSecret(d []byte) []byte {
if len(d) > x25519lib.Size {
return nil
}
// Ensure truncated leading bytes are re-added
secret := make([]byte, x25519lib.Size)
copyReversed(secret, d)
return secret
}
// generateKeyPairBytes Generates a private-public key-pair.
// 'priv' is a private key; a little-endian scalar belonging to the set
// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of the
// curve. 'pub' is simply 'priv' * G where G is the base point.
// See https://cr.yp.to/ecdh.html and RFC7748, sec 5.
func (c *curve25519) generateKeyPairBytes(rand io.Reader) (priv, pub x25519lib.Key, err error) {
_, err = io.ReadFull(rand, priv[:])
if err != nil {
return
}
x25519lib.KeyGen(&pub, &priv)
return
}
func (c *curve25519) GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error) {
priv, pub, err := c.generateKeyPairBytes(rand)
if err != nil {
return
}
return pub[:], priv[:], nil
}
func (c *genericCurve) MaskSecret(secret []byte) []byte {
return secret
}
func (c *curve25519) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
// RFC6637 §8: "Generate an ephemeral key pair {v, V=vG}"
// ephemeralPrivate corresponds to `v`.
// ephemeralPublic corresponds to `V`.
ephemeralPrivate, ephemeralPublic, err := c.generateKeyPairBytes(rand)
if err != nil {
return nil, nil, err
}
// RFC6637 §8: "Obtain the authenticated recipient public key R"
// pubKey corresponds to `R`.
var pubKey x25519lib.Key
copy(pubKey[:], point)
// RFC6637 §8: "Compute the shared point S = vR"
// "VB = convert point V to the octet string"
// sharedPoint corresponds to `VB`.
var sharedPoint x25519lib.Key
x25519lib.Shared(&sharedPoint, &ephemeralPrivate, &pubKey)
return ephemeralPublic[:], sharedPoint[:], nil
}
func (c *curve25519) Decaps(vsG, secret []byte) (sharedSecret []byte, err error) {
var ephemeralPublic, decodedPrivate, sharedPoint x25519lib.Key
// RFC6637 §8: "The decryption is the inverse of the method given."
// All quoted descriptions in comments below describe encryption, and
// the reverse is performed.
// vsG corresponds to `VB` in RFC6637 §8 .
// RFC6637 §8: "VB = convert point V to the octet string"
copy(ephemeralPublic[:], vsG)
// decodedPrivate corresponds to `r` in RFC6637 §8 .
copy(decodedPrivate[:], secret)
// RFC6637 §8: "Note that the recipient obtains the shared secret by calculating
// S = rV = rvG, where (r,R) is the recipient's key pair."
// sharedPoint corresponds to `S`.
x25519lib.Shared(&sharedPoint, &decodedPrivate, &ephemeralPublic)
return sharedPoint[:], nil
}
func (c *curve25519) ValidateECDH(point []byte, secret []byte) (err error) {
var pk, sk x25519lib.Key
copy(sk[:], secret)
x25519lib.KeyGen(&pk, &sk)
if subtle.ConstantTimeCompare(point, pk[:]) == 0 {
return errors.KeyInvalidError("ecc: invalid curve25519 public point")
}
return nil
}
func copyReversed(out []byte, in []byte) {
l := len(in)
for i := 0; i < l; i++ {
out[i] = in[l-i-1]
}
}

View File

@@ -0,0 +1,143 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"bytes"
"crypto/elliptic"
"github.com/ProtonMail/go-crypto/bitcurves"
"github.com/ProtonMail/go-crypto/brainpool"
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
)
const Curve25519GenName = "Curve25519"
type CurveInfo struct {
GenName string
Oid *encoding.OID
Curve Curve
}
var Curves = []CurveInfo{
{
// NIST P-256
GenName: "P256",
Oid: encoding.NewOID([]byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}),
Curve: NewGenericCurve(elliptic.P256()),
},
{
// NIST P-384
GenName: "P384",
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x22}),
Curve: NewGenericCurve(elliptic.P384()),
},
{
// NIST P-521
GenName: "P521",
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x23}),
Curve: NewGenericCurve(elliptic.P521()),
},
{
// SecP256k1
GenName: "SecP256k1",
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x0A}),
Curve: NewGenericCurve(bitcurves.S256()),
},
{
// Curve25519
GenName: Curve25519GenName,
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}),
Curve: NewCurve25519(),
},
{
// x448
GenName: "Curve448",
Oid: encoding.NewOID([]byte{0x2B, 0x65, 0x6F}),
Curve: NewX448(),
},
{
// Ed25519
GenName: Curve25519GenName,
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01}),
Curve: NewEd25519(),
},
{
// Ed448
GenName: "Curve448",
Oid: encoding.NewOID([]byte{0x2B, 0x65, 0x71}),
Curve: NewEd448(),
},
{
// BrainpoolP256r1
GenName: "BrainpoolP256",
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}),
Curve: NewGenericCurve(brainpool.P256r1()),
},
{
// BrainpoolP384r1
GenName: "BrainpoolP384",
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}),
Curve: NewGenericCurve(brainpool.P384r1()),
},
{
// BrainpoolP512r1
GenName: "BrainpoolP512",
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}),
Curve: NewGenericCurve(brainpool.P512r1()),
},
}
func FindByCurve(curve Curve) *CurveInfo {
for _, curveInfo := range Curves {
if curveInfo.Curve.GetCurveName() == curve.GetCurveName() {
return &curveInfo
}
}
return nil
}
func FindByOid(oid encoding.Field) *CurveInfo {
var rawBytes = oid.Bytes()
for _, curveInfo := range Curves {
if bytes.Equal(curveInfo.Oid.Bytes(), rawBytes) {
return &curveInfo
}
}
return nil
}
func FindEdDSAByGenName(curveGenName string) EdDSACurve {
for _, curveInfo := range Curves {
if curveInfo.GenName == curveGenName {
curve, ok := curveInfo.Curve.(EdDSACurve)
if ok {
return curve
}
}
}
return nil
}
func FindECDSAByGenName(curveGenName string) ECDSACurve {
for _, curveInfo := range Curves {
if curveInfo.GenName == curveGenName {
curve, ok := curveInfo.Curve.(ECDSACurve)
if ok {
return curve
}
}
}
return nil
}
func FindECDHByGenName(curveGenName string) ECDHCurve {
for _, curveInfo := range Curves {
if curveInfo.GenName == curveGenName {
curve, ok := curveInfo.Curve.(ECDHCurve)
if ok {
return curve
}
}
}
return nil
}

View File

@@ -0,0 +1,48 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"io"
"math/big"
)
type Curve interface {
GetCurveName() string
}
type ECDSACurve interface {
Curve
MarshalIntegerPoint(x, y *big.Int) []byte
UnmarshalIntegerPoint([]byte) (x, y *big.Int)
MarshalIntegerSecret(d *big.Int) []byte
UnmarshalIntegerSecret(d []byte) *big.Int
GenerateECDSA(rand io.Reader) (x, y, secret *big.Int, err error)
Sign(rand io.Reader, x, y, d *big.Int, hash []byte) (r, s *big.Int, err error)
Verify(x, y *big.Int, hash []byte, r, s *big.Int) bool
ValidateECDSA(x, y *big.Int, secret []byte) error
}
type EdDSACurve interface {
Curve
MarshalBytePoint(x []byte) []byte
UnmarshalBytePoint([]byte) (x []byte)
MarshalByteSecret(d []byte) []byte
UnmarshalByteSecret(d []byte) []byte
MarshalSignature(sig []byte) (r, s []byte)
UnmarshalSignature(r, s []byte) (sig []byte)
GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error)
Sign(publicKey, privateKey, message []byte) (sig []byte, err error)
Verify(publicKey, message, sig []byte) bool
ValidateEdDSA(publicKey, privateKey []byte) (err error)
}
type ECDHCurve interface {
Curve
MarshalBytePoint([]byte) (encoded []byte)
UnmarshalBytePoint(encoded []byte) []byte
MarshalByteSecret(d []byte) []byte
UnmarshalByteSecret(d []byte) []byte
GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error)
Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error)
Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error)
ValidateECDH(public []byte, secret []byte) error
}

View File

@@ -0,0 +1,120 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"bytes"
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
ed25519lib "github.com/cloudflare/circl/sign/ed25519"
)
const ed25519Size = 32
type ed25519 struct{}
func NewEd25519() *ed25519 {
return &ed25519{}
}
func (c *ed25519) GetCurveName() string {
return "ed25519"
}
// MarshalBytePoint encodes the public point from native format, adding the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed25519) MarshalBytePoint(x []byte) []byte {
return append([]byte{0x40}, x...)
}
// UnmarshalBytePoint decodes a point from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed25519) UnmarshalBytePoint(point []byte) (x []byte) {
if len(point) != ed25519lib.PublicKeySize+1 {
return nil
}
// Return unprefixed
return point[1:]
}
// MarshalByteSecret encodes a scalar in native format.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed25519) MarshalByteSecret(d []byte) []byte {
return d
}
// UnmarshalByteSecret decodes a scalar in native format and re-adds the stripped leading zeroes
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed25519) UnmarshalByteSecret(s []byte) (d []byte) {
if len(s) > ed25519lib.SeedSize {
return nil
}
// Handle stripped leading zeroes
d = make([]byte, ed25519lib.SeedSize)
copy(d[ed25519lib.SeedSize-len(s):], s)
return
}
// MarshalSignature splits a signature in R and S.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.1
func (c *ed25519) MarshalSignature(sig []byte) (r, s []byte) {
return sig[:ed25519Size], sig[ed25519Size:]
}
// UnmarshalSignature decodes R and S in the native format, re-adding the stripped leading zeroes
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.1
func (c *ed25519) UnmarshalSignature(r, s []byte) (sig []byte) {
// Check size
if len(r) > 32 || len(s) > 32 {
return nil
}
sig = make([]byte, ed25519lib.SignatureSize)
// Handle stripped leading zeroes
copy(sig[ed25519Size-len(r):ed25519Size], r)
copy(sig[ed25519lib.SignatureSize-len(s):], s)
return sig
}
func (c *ed25519) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) {
pk, sk, err := ed25519lib.GenerateKey(rand)
if err != nil {
return nil, nil, err
}
return pk, sk[:ed25519lib.SeedSize], nil
}
func getEd25519Sk(publicKey, privateKey []byte) ed25519lib.PrivateKey {
privateKeyCap, privateKeyLen, publicKeyLen := cap(privateKey), len(privateKey), len(publicKey)
if privateKeyCap >= privateKeyLen+publicKeyLen &&
bytes.Equal(privateKey[privateKeyLen:privateKeyLen+publicKeyLen], publicKey) {
return privateKey[:privateKeyLen+publicKeyLen]
}
return append(privateKey[:privateKeyLen:privateKeyLen], publicKey...)
}
func (c *ed25519) Sign(publicKey, privateKey, message []byte) (sig []byte, err error) {
sig = ed25519lib.Sign(getEd25519Sk(publicKey, privateKey), message)
return sig, nil
}
func (c *ed25519) Verify(publicKey, message, sig []byte) bool {
return ed25519lib.Verify(publicKey, message, sig)
}
func (c *ed25519) ValidateEdDSA(publicKey, privateKey []byte) (err error) {
priv := getEd25519Sk(publicKey, privateKey)
expectedPriv := ed25519lib.NewKeyFromSeed(priv.Seed())
if subtle.ConstantTimeCompare(priv, expectedPriv) == 0 {
return errors.KeyInvalidError("ecc: invalid ed25519 secret")
}
return nil
}

View File

@@ -0,0 +1,119 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"bytes"
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
ed448lib "github.com/cloudflare/circl/sign/ed448"
)
type ed448 struct{}
func NewEd448() *ed448 {
return &ed448{}
}
func (c *ed448) GetCurveName() string {
return "ed448"
}
// MarshalBytePoint encodes the public point from native format, adding the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed448) MarshalBytePoint(x []byte) []byte {
// Return prefixed
return append([]byte{0x40}, x...)
}
// UnmarshalBytePoint decodes a point from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed448) UnmarshalBytePoint(point []byte) (x []byte) {
if len(point) != ed448lib.PublicKeySize+1 {
return nil
}
// Strip prefix
return point[1:]
}
// MarshalByteSecret encoded a scalar from native format to prefixed.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed448) MarshalByteSecret(d []byte) []byte {
// Return prefixed
return append([]byte{0x40}, d...)
}
// UnmarshalByteSecret decodes a scalar from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed448) UnmarshalByteSecret(s []byte) (d []byte) {
// Check prefixed size
if len(s) != ed448lib.SeedSize+1 {
return nil
}
// Strip prefix
return s[1:]
}
// MarshalSignature splits a signature in R and S, where R is in prefixed native format and
// S is an MPI with value zero.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.2
func (c *ed448) MarshalSignature(sig []byte) (r, s []byte) {
return append([]byte{0x40}, sig...), []byte{}
}
// UnmarshalSignature decodes R and S in the native format. Only R is used, in prefixed native format.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.2
func (c *ed448) UnmarshalSignature(r, s []byte) (sig []byte) {
if len(r) != ed448lib.SignatureSize+1 {
return nil
}
return r[1:]
}
func (c *ed448) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) {
pk, sk, err := ed448lib.GenerateKey(rand)
if err != nil {
return nil, nil, err
}
return pk, sk[:ed448lib.SeedSize], nil
}
func getEd448Sk(publicKey, privateKey []byte) ed448lib.PrivateKey {
privateKeyCap, privateKeyLen, publicKeyLen := cap(privateKey), len(privateKey), len(publicKey)
if privateKeyCap >= privateKeyLen+publicKeyLen &&
bytes.Equal(privateKey[privateKeyLen:privateKeyLen+publicKeyLen], publicKey) {
return privateKey[:privateKeyLen+publicKeyLen]
}
return append(privateKey[:privateKeyLen:privateKeyLen], publicKey...)
}
func (c *ed448) Sign(publicKey, privateKey, message []byte) (sig []byte, err error) {
// Ed448 is used with the empty string as a context string.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7
sig = ed448lib.Sign(getEd448Sk(publicKey, privateKey), message, "")
return sig, nil
}
func (c *ed448) Verify(publicKey, message, sig []byte) bool {
// Ed448 is used with the empty string as a context string.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7
return ed448lib.Verify(publicKey, message, sig, "")
}
func (c *ed448) ValidateEdDSA(publicKey, privateKey []byte) (err error) {
priv := getEd448Sk(publicKey, privateKey)
expectedPriv := ed448lib.NewKeyFromSeed(priv.Seed())
if subtle.ConstantTimeCompare(priv, expectedPriv) == 0 {
return errors.KeyInvalidError("ecc: invalid ed448 secret")
}
return nil
}

View File

@@ -0,0 +1,149 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"crypto/ecdsa"
"crypto/elliptic"
"fmt"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"io"
"math/big"
)
type genericCurve struct {
Curve elliptic.Curve
}
func NewGenericCurve(c elliptic.Curve) *genericCurve {
return &genericCurve{
Curve: c,
}
}
func (c *genericCurve) GetCurveName() string {
return c.Curve.Params().Name
}
func (c *genericCurve) MarshalBytePoint(point []byte) []byte {
return point
}
func (c *genericCurve) UnmarshalBytePoint(point []byte) []byte {
return point
}
func (c *genericCurve) MarshalIntegerPoint(x, y *big.Int) []byte {
return elliptic.Marshal(c.Curve, x, y)
}
func (c *genericCurve) UnmarshalIntegerPoint(point []byte) (x, y *big.Int) {
return elliptic.Unmarshal(c.Curve, point)
}
func (c *genericCurve) MarshalByteSecret(d []byte) []byte {
return d
}
func (c *genericCurve) UnmarshalByteSecret(d []byte) []byte {
return d
}
func (c *genericCurve) MarshalIntegerSecret(d *big.Int) []byte {
return d.Bytes()
}
func (c *genericCurve) UnmarshalIntegerSecret(d []byte) *big.Int {
return new(big.Int).SetBytes(d)
}
func (c *genericCurve) GenerateECDH(rand io.Reader) (point, secret []byte, err error) {
secret, x, y, err := elliptic.GenerateKey(c.Curve, rand)
if err != nil {
return nil, nil, err
}
point = elliptic.Marshal(c.Curve, x, y)
return point, secret, nil
}
func (c *genericCurve) GenerateECDSA(rand io.Reader) (x, y, secret *big.Int, err error) {
priv, err := ecdsa.GenerateKey(c.Curve, rand)
if err != nil {
return
}
return priv.X, priv.Y, priv.D, nil
}
func (c *genericCurve) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
xP, yP := elliptic.Unmarshal(c.Curve, point)
if xP == nil {
panic("invalid point")
}
d, x, y, err := elliptic.GenerateKey(c.Curve, rand)
if err != nil {
return nil, nil, err
}
vsG := elliptic.Marshal(c.Curve, x, y)
zbBig, _ := c.Curve.ScalarMult(xP, yP, d)
byteLen := (c.Curve.Params().BitSize + 7) >> 3
zb := make([]byte, byteLen)
zbBytes := zbBig.Bytes()
copy(zb[byteLen-len(zbBytes):], zbBytes)
return vsG, zb, nil
}
func (c *genericCurve) Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) {
x, y := elliptic.Unmarshal(c.Curve, ephemeral)
zbBig, _ := c.Curve.ScalarMult(x, y, secret)
byteLen := (c.Curve.Params().BitSize + 7) >> 3
zb := make([]byte, byteLen)
zbBytes := zbBig.Bytes()
copy(zb[byteLen-len(zbBytes):], zbBytes)
return zb, nil
}
func (c *genericCurve) Sign(rand io.Reader, x, y, d *big.Int, hash []byte) (r, s *big.Int, err error) {
priv := &ecdsa.PrivateKey{D: d, PublicKey: ecdsa.PublicKey{X: x, Y: y, Curve: c.Curve}}
return ecdsa.Sign(rand, priv, hash)
}
func (c *genericCurve) Verify(x, y *big.Int, hash []byte, r, s *big.Int) bool {
pub := &ecdsa.PublicKey{X: x, Y: y, Curve: c.Curve}
return ecdsa.Verify(pub, hash, r, s)
}
func (c *genericCurve) validate(xP, yP *big.Int, secret []byte) error {
// the public point should not be at infinity (0,0)
zero := new(big.Int)
if xP.Cmp(zero) == 0 && yP.Cmp(zero) == 0 {
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): infinity point", c.Curve.Params().Name))
}
// re-derive the public point Q' = (X,Y) = dG
// to compare to declared Q in public key
expectedX, expectedY := c.Curve.ScalarBaseMult(secret)
if xP.Cmp(expectedX) != 0 || yP.Cmp(expectedY) != 0 {
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name))
}
return nil
}
func (c *genericCurve) ValidateECDSA(xP, yP *big.Int, secret []byte) error {
return c.validate(xP, yP, secret)
}
func (c *genericCurve) ValidateECDH(point []byte, secret []byte) error {
xP, yP := elliptic.Unmarshal(c.Curve, point)
if xP == nil {
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name))
}
return c.validate(xP, yP, secret)
}

View File

@@ -0,0 +1,107 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
x448lib "github.com/cloudflare/circl/dh/x448"
)
type x448 struct{}
func NewX448() *x448 {
return &x448{}
}
func (c *x448) GetCurveName() string {
return "x448"
}
// MarshalBytePoint encodes the public point from native format, adding the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
func (c *x448) MarshalBytePoint(point []byte) []byte {
return append([]byte{0x40}, point...)
}
// UnmarshalBytePoint decodes a point from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
func (c *x448) UnmarshalBytePoint(point []byte) []byte {
if len(point) != x448lib.Size+1 {
return nil
}
return point[1:]
}
// MarshalByteSecret encoded a scalar from native format to prefixed.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.2
func (c *x448) MarshalByteSecret(d []byte) []byte {
return append([]byte{0x40}, d...)
}
// UnmarshalByteSecret decodes a scalar from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.2
func (c *x448) UnmarshalByteSecret(d []byte) []byte {
if len(d) != x448lib.Size+1 {
return nil
}
// Store without prefix
return d[1:]
}
func (c *x448) generateKeyPairBytes(rand io.Reader) (sk, pk x448lib.Key, err error) {
if _, err = rand.Read(sk[:]); err != nil {
return
}
x448lib.KeyGen(&pk, &sk)
return
}
func (c *x448) GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error) {
priv, pub, err := c.generateKeyPairBytes(rand)
if err != nil {
return
}
return pub[:], priv[:], nil
}
func (c *x448) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
var pk, ss x448lib.Key
seed, e, err := c.generateKeyPairBytes(rand)
if err != nil {
return nil, nil, err
}
copy(pk[:], point)
x448lib.Shared(&ss, &seed, &pk)
return e[:], ss[:], nil
}
func (c *x448) Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) {
var ss, sk, e x448lib.Key
copy(sk[:], secret)
copy(e[:], ephemeral)
x448lib.Shared(&ss, &sk, &e)
return ss[:], nil
}
func (c *x448) ValidateECDH(point []byte, secret []byte) error {
var sk, pk, expectedPk x448lib.Key
copy(pk[:], point)
copy(sk[:], secret)
x448lib.KeyGen(&expectedPk, &sk)
if subtle.ConstantTimeCompare(expectedPk[:], pk[:]) == 0 {
return errors.KeyInvalidError("ecc: invalid curve25519 public point")
}
return nil
}

View File

@@ -0,0 +1,27 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package encoding implements openpgp packet field encodings as specified in
// RFC 4880 and 6637.
package encoding
import "io"
// Field is an encoded field of an openpgp packet.
type Field interface {
// Bytes returns the decoded data.
Bytes() []byte
// BitLength is the size in bits of the decoded data.
BitLength() uint16
// EncodedBytes returns the encoded data.
EncodedBytes() []byte
// EncodedLength is the size in bytes of the encoded data.
EncodedLength() uint16
// ReadFrom reads the next Field from r.
ReadFrom(r io.Reader) (int64, error)
}

View File

@@ -0,0 +1,91 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package encoding
import (
"io"
"math/big"
"math/bits"
)
// An MPI is used to store the contents of a big integer, along with the bit
// length that was specified in the original input. This allows the MPI to be
// reserialized exactly.
type MPI struct {
bytes []byte
bitLength uint16
}
// NewMPI returns a MPI initialized with bytes.
func NewMPI(bytes []byte) *MPI {
for len(bytes) != 0 && bytes[0] == 0 {
bytes = bytes[1:]
}
if len(bytes) == 0 {
bitLength := uint16(0)
return &MPI{bytes, bitLength}
}
bitLength := 8*uint16(len(bytes)-1) + uint16(bits.Len8(bytes[0]))
return &MPI{bytes, bitLength}
}
// Bytes returns the decoded data.
func (m *MPI) Bytes() []byte {
return m.bytes
}
// BitLength is the size in bits of the decoded data.
func (m *MPI) BitLength() uint16 {
return m.bitLength
}
// EncodedBytes returns the encoded data.
func (m *MPI) EncodedBytes() []byte {
return append([]byte{byte(m.bitLength >> 8), byte(m.bitLength)}, m.bytes...)
}
// EncodedLength is the size in bytes of the encoded data.
func (m *MPI) EncodedLength() uint16 {
return uint16(2 + len(m.bytes))
}
// ReadFrom reads into m the next MPI from r.
func (m *MPI) ReadFrom(r io.Reader) (int64, error) {
var buf [2]byte
n, err := io.ReadFull(r, buf[0:])
if err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return int64(n), err
}
m.bitLength = uint16(buf[0])<<8 | uint16(buf[1])
m.bytes = make([]byte, (int(m.bitLength)+7)/8)
nn, err := io.ReadFull(r, m.bytes)
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
// remove leading zero bytes from malformed GnuPG encoded MPIs:
// https://bugs.gnupg.org/gnupg/issue1853
// for _, b := range m.bytes {
// if b != 0 {
// break
// }
// m.bytes = m.bytes[1:]
// m.bitLength -= 8
// }
return int64(n) + int64(nn), err
}
// SetBig initializes m with the bits from n.
func (m *MPI) SetBig(n *big.Int) *MPI {
m.bytes = n.Bytes()
m.bitLength = uint16(n.BitLen())
return m
}

View File

@@ -0,0 +1,88 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package encoding
import (
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
// OID is used to store a variable-length field with a one-octet size
// prefix. See https://tools.ietf.org/html/rfc6637#section-9.
type OID struct {
bytes []byte
}
const (
// maxOID is the maximum number of bytes in a OID.
maxOID = 254
// reservedOIDLength1 and reservedOIDLength2 are OID lengths that the RFC
// specifies are reserved.
reservedOIDLength1 = 0
reservedOIDLength2 = 0xff
)
// NewOID returns a OID initialized with bytes.
func NewOID(bytes []byte) *OID {
switch len(bytes) {
case reservedOIDLength1, reservedOIDLength2:
panic("encoding: NewOID argument length is reserved")
default:
if len(bytes) > maxOID {
panic("encoding: NewOID argument too large")
}
}
return &OID{
bytes: bytes,
}
}
// Bytes returns the decoded data.
func (o *OID) Bytes() []byte {
return o.bytes
}
// BitLength is the size in bits of the decoded data.
func (o *OID) BitLength() uint16 {
return uint16(len(o.bytes) * 8)
}
// EncodedBytes returns the encoded data.
func (o *OID) EncodedBytes() []byte {
return append([]byte{byte(len(o.bytes))}, o.bytes...)
}
// EncodedLength is the size in bytes of the encoded data.
func (o *OID) EncodedLength() uint16 {
return uint16(1 + len(o.bytes))
}
// ReadFrom reads into b the next OID from r.
func (o *OID) ReadFrom(r io.Reader) (int64, error) {
var buf [1]byte
n, err := io.ReadFull(r, buf[:])
if err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return int64(n), err
}
switch buf[0] {
case reservedOIDLength1, reservedOIDLength2:
return int64(n), errors.UnsupportedError("reserved for future extensions")
}
o.bytes = make([]byte, buf[0])
nn, err := io.ReadFull(r, o.bytes)
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return int64(n) + int64(nn), err
}

View File

@@ -0,0 +1,456 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package openpgp
import (
"crypto"
"crypto/rand"
"crypto/rsa"
goerrors "errors"
"io"
"math/big"
"time"
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
"github.com/ProtonMail/go-crypto/openpgp/ed25519"
"github.com/ProtonMail/go-crypto/openpgp/ed448"
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
"github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/ProtonMail/go-crypto/openpgp/x25519"
"github.com/ProtonMail/go-crypto/openpgp/x448"
)
// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
// single identity composed of the given full name, comment and email, any of
// which may be empty but must not contain any of "()<>\x00".
// If config is nil, sensible defaults will be used.
func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
creationTime := config.Now()
keyLifetimeSecs := config.KeyLifetime()
// Generate a primary signing key
primaryPrivRaw, err := newSigner(config)
if err != nil {
return nil, err
}
primary := packet.NewSignerPrivateKey(creationTime, primaryPrivRaw)
if config.V6() {
if err := primary.UpgradeToV6(); err != nil {
return nil, err
}
}
e := &Entity{
PrimaryKey: &primary.PublicKey,
PrivateKey: primary,
Identities: make(map[string]*Identity),
Subkeys: []Subkey{},
Signatures: []*packet.Signature{},
}
if config.V6() {
// In v6 keys algorithm preferences should be stored in direct key signatures
selfSignature := createSignaturePacket(&primary.PublicKey, packet.SigTypeDirectSignature, config)
err = writeKeyProperties(selfSignature, creationTime, keyLifetimeSecs, config)
if err != nil {
return nil, err
}
err = selfSignature.SignDirectKeyBinding(&primary.PublicKey, primary, config)
if err != nil {
return nil, err
}
e.Signatures = append(e.Signatures, selfSignature)
e.SelfSignature = selfSignature
}
err = e.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs, !config.V6())
if err != nil {
return nil, err
}
// NOTE: No key expiry here, but we will not return this subkey in EncryptionKey()
// if the primary/master key has expired.
err = e.addEncryptionSubkey(config, creationTime, 0)
if err != nil {
return nil, err
}
return e, nil
}
func (t *Entity) AddUserId(name, comment, email string, config *packet.Config) error {
creationTime := config.Now()
keyLifetimeSecs := config.KeyLifetime()
return t.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs, !config.V6())
}
func writeKeyProperties(selfSignature *packet.Signature, creationTime time.Time, keyLifetimeSecs uint32, config *packet.Config) error {
advertiseAead := config.AEAD() != nil
selfSignature.CreationTime = creationTime
selfSignature.KeyLifetimeSecs = &keyLifetimeSecs
selfSignature.FlagsValid = true
selfSignature.FlagSign = true
selfSignature.FlagCertify = true
selfSignature.SEIPDv1 = true // true by default, see 5.8 vs. 5.14
selfSignature.SEIPDv2 = advertiseAead
// Set the PreferredHash for the SelfSignature from the packet.Config.
// If it is not the must-implement algorithm from rfc4880bis, append that.
hash, ok := algorithm.HashToHashId(config.Hash())
if !ok {
return errors.UnsupportedError("unsupported preferred hash function")
}
selfSignature.PreferredHash = []uint8{hash}
if config.Hash() != crypto.SHA256 {
selfSignature.PreferredHash = append(selfSignature.PreferredHash, hashToHashId(crypto.SHA256))
}
// Likewise for DefaultCipher.
selfSignature.PreferredSymmetric = []uint8{uint8(config.Cipher())}
if config.Cipher() != packet.CipherAES128 {
selfSignature.PreferredSymmetric = append(selfSignature.PreferredSymmetric, uint8(packet.CipherAES128))
}
// We set CompressionNone as the preferred compression algorithm because
// of compression side channel attacks, then append the configured
// DefaultCompressionAlgo if any is set (to signal support for cases
// where the application knows that using compression is safe).
selfSignature.PreferredCompression = []uint8{uint8(packet.CompressionNone)}
if config.Compression() != packet.CompressionNone {
selfSignature.PreferredCompression = append(selfSignature.PreferredCompression, uint8(config.Compression()))
}
if advertiseAead {
// Get the preferred AEAD mode from the packet.Config.
// If it is not the must-implement algorithm from rfc9580, append that.
modes := []uint8{uint8(config.AEAD().Mode())}
if config.AEAD().Mode() != packet.AEADModeOCB {
modes = append(modes, uint8(packet.AEADModeOCB))
}
// For preferred (AES256, GCM), we'll generate (AES256, GCM), (AES256, OCB), (AES128, GCM), (AES128, OCB)
for _, cipher := range selfSignature.PreferredSymmetric {
for _, mode := range modes {
selfSignature.PreferredCipherSuites = append(selfSignature.PreferredCipherSuites, [2]uint8{cipher, mode})
}
}
}
return nil
}
func (t *Entity) addUserId(name, comment, email string, config *packet.Config, creationTime time.Time, keyLifetimeSecs uint32, writeProperties bool) error {
uid := packet.NewUserId(name, comment, email)
if uid == nil {
return errors.InvalidArgumentError("user id field contained invalid characters")
}
if _, ok := t.Identities[uid.Id]; ok {
return errors.InvalidArgumentError("user id exist")
}
primary := t.PrivateKey
isPrimaryId := len(t.Identities) == 0
selfSignature := createSignaturePacket(&primary.PublicKey, packet.SigTypePositiveCert, config)
if writeProperties {
err := writeKeyProperties(selfSignature, creationTime, keyLifetimeSecs, config)
if err != nil {
return err
}
}
selfSignature.IsPrimaryId = &isPrimaryId
// User ID binding signature
err := selfSignature.SignUserId(uid.Id, &primary.PublicKey, primary, config)
if err != nil {
return err
}
t.Identities[uid.Id] = &Identity{
Name: uid.Id,
UserId: uid,
SelfSignature: selfSignature,
Signatures: []*packet.Signature{selfSignature},
}
return nil
}
// AddSigningSubkey adds a signing keypair as a subkey to the Entity.
// If config is nil, sensible defaults will be used.
func (e *Entity) AddSigningSubkey(config *packet.Config) error {
creationTime := config.Now()
keyLifetimeSecs := config.KeyLifetime()
subPrivRaw, err := newSigner(config)
if err != nil {
return err
}
sub := packet.NewSignerPrivateKey(creationTime, subPrivRaw)
sub.IsSubkey = true
if config.V6() {
if err := sub.UpgradeToV6(); err != nil {
return err
}
}
subkey := Subkey{
PublicKey: &sub.PublicKey,
PrivateKey: sub,
}
subkey.Sig = createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyBinding, config)
subkey.Sig.CreationTime = creationTime
subkey.Sig.KeyLifetimeSecs = &keyLifetimeSecs
subkey.Sig.FlagsValid = true
subkey.Sig.FlagSign = true
subkey.Sig.EmbeddedSignature = createSignaturePacket(subkey.PublicKey, packet.SigTypePrimaryKeyBinding, config)
subkey.Sig.EmbeddedSignature.CreationTime = creationTime
err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey, subkey.PrivateKey, config)
if err != nil {
return err
}
err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
if err != nil {
return err
}
e.Subkeys = append(e.Subkeys, subkey)
return nil
}
// AddEncryptionSubkey adds an encryption keypair as a subkey to the Entity.
// If config is nil, sensible defaults will be used.
func (e *Entity) AddEncryptionSubkey(config *packet.Config) error {
creationTime := config.Now()
keyLifetimeSecs := config.KeyLifetime()
return e.addEncryptionSubkey(config, creationTime, keyLifetimeSecs)
}
func (e *Entity) addEncryptionSubkey(config *packet.Config, creationTime time.Time, keyLifetimeSecs uint32) error {
subPrivRaw, err := newDecrypter(config)
if err != nil {
return err
}
sub := packet.NewDecrypterPrivateKey(creationTime, subPrivRaw)
sub.IsSubkey = true
if config.V6() {
if err := sub.UpgradeToV6(); err != nil {
return err
}
}
subkey := Subkey{
PublicKey: &sub.PublicKey,
PrivateKey: sub,
}
subkey.Sig = createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyBinding, config)
subkey.Sig.CreationTime = creationTime
subkey.Sig.KeyLifetimeSecs = &keyLifetimeSecs
subkey.Sig.FlagsValid = true
subkey.Sig.FlagEncryptStorage = true
subkey.Sig.FlagEncryptCommunications = true
err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
if err != nil {
return err
}
e.Subkeys = append(e.Subkeys, subkey)
return nil
}
// Generates a signing key
func newSigner(config *packet.Config) (signer interface{}, err error) {
switch config.PublicKeyAlgorithm() {
case packet.PubKeyAlgoRSA:
bits := config.RSAModulusBits()
if bits < 1024 {
return nil, errors.InvalidArgumentError("bits must be >= 1024")
}
if config != nil && len(config.RSAPrimes) >= 2 {
primes := config.RSAPrimes[0:2]
config.RSAPrimes = config.RSAPrimes[2:]
return generateRSAKeyWithPrimes(config.Random(), 2, bits, primes)
}
return rsa.GenerateKey(config.Random(), bits)
case packet.PubKeyAlgoEdDSA:
if config.V6() {
// Implementations MUST NOT accept or generate v6 key material
// using the deprecated OIDs.
return nil, errors.InvalidArgumentError("EdDSALegacy cannot be used for v6 keys")
}
curve := ecc.FindEdDSAByGenName(string(config.CurveName()))
if curve == nil {
return nil, errors.InvalidArgumentError("unsupported curve")
}
priv, err := eddsa.GenerateKey(config.Random(), curve)
if err != nil {
return nil, err
}
return priv, nil
case packet.PubKeyAlgoECDSA:
curve := ecc.FindECDSAByGenName(string(config.CurveName()))
if curve == nil {
return nil, errors.InvalidArgumentError("unsupported curve")
}
priv, err := ecdsa.GenerateKey(config.Random(), curve)
if err != nil {
return nil, err
}
return priv, nil
case packet.PubKeyAlgoEd25519:
priv, err := ed25519.GenerateKey(config.Random())
if err != nil {
return nil, err
}
return priv, nil
case packet.PubKeyAlgoEd448:
priv, err := ed448.GenerateKey(config.Random())
if err != nil {
return nil, err
}
return priv, nil
default:
return nil, errors.InvalidArgumentError("unsupported public key algorithm")
}
}
// Generates an encryption/decryption key
func newDecrypter(config *packet.Config) (decrypter interface{}, err error) {
switch config.PublicKeyAlgorithm() {
case packet.PubKeyAlgoRSA:
bits := config.RSAModulusBits()
if bits < 1024 {
return nil, errors.InvalidArgumentError("bits must be >= 1024")
}
if config != nil && len(config.RSAPrimes) >= 2 {
primes := config.RSAPrimes[0:2]
config.RSAPrimes = config.RSAPrimes[2:]
return generateRSAKeyWithPrimes(config.Random(), 2, bits, primes)
}
return rsa.GenerateKey(config.Random(), bits)
case packet.PubKeyAlgoEdDSA, packet.PubKeyAlgoECDSA:
fallthrough // When passing EdDSA or ECDSA, we generate an ECDH subkey
case packet.PubKeyAlgoECDH:
if config.V6() &&
(config.CurveName() == packet.Curve25519 ||
config.CurveName() == packet.Curve448) {
// Implementations MUST NOT accept or generate v6 key material
// using the deprecated OIDs.
return nil, errors.InvalidArgumentError("ECDH with Curve25519/448 legacy cannot be used for v6 keys")
}
var kdf = ecdh.KDF{
Hash: algorithm.SHA512,
Cipher: algorithm.AES256,
}
curve := ecc.FindECDHByGenName(string(config.CurveName()))
if curve == nil {
return nil, errors.InvalidArgumentError("unsupported curve")
}
return ecdh.GenerateKey(config.Random(), curve, kdf)
case packet.PubKeyAlgoEd25519, packet.PubKeyAlgoX25519: // When passing Ed25519, we generate an x25519 subkey
return x25519.GenerateKey(config.Random())
case packet.PubKeyAlgoEd448, packet.PubKeyAlgoX448: // When passing Ed448, we generate an x448 subkey
return x448.GenerateKey(config.Random())
default:
return nil, errors.InvalidArgumentError("unsupported public key algorithm")
}
}
var bigOne = big.NewInt(1)
// generateRSAKeyWithPrimes generates a multi-prime RSA keypair of the
// given bit size, using the given random source and pre-populated primes.
func generateRSAKeyWithPrimes(random io.Reader, nprimes int, bits int, prepopulatedPrimes []*big.Int) (*rsa.PrivateKey, error) {
priv := new(rsa.PrivateKey)
priv.E = 65537
if nprimes < 2 {
return nil, goerrors.New("generateRSAKeyWithPrimes: nprimes must be >= 2")
}
if bits < 1024 {
return nil, goerrors.New("generateRSAKeyWithPrimes: bits must be >= 1024")
}
primes := make([]*big.Int, nprimes)
NextSetOfPrimes:
for {
todo := bits
// crypto/rand should set the top two bits in each prime.
// Thus each prime has the form
// p_i = 2^bitlen(p_i) × 0.11... (in base 2).
// And the product is:
// P = 2^todo × α
// where α is the product of nprimes numbers of the form 0.11...
//
// If α < 1/2 (which can happen for nprimes > 2), we need to
// shift todo to compensate for lost bits: the mean value of 0.11...
// is 7/8, so todo + shift - nprimes * log2(7/8) ~= bits - 1/2
// will give good results.
if nprimes >= 7 {
todo += (nprimes - 2) / 5
}
for i := 0; i < nprimes; i++ {
var err error
if len(prepopulatedPrimes) == 0 {
primes[i], err = rand.Prime(random, todo/(nprimes-i))
if err != nil {
return nil, err
}
} else {
primes[i] = prepopulatedPrimes[0]
prepopulatedPrimes = prepopulatedPrimes[1:]
}
todo -= primes[i].BitLen()
}
// Make sure that primes is pairwise unequal.
for i, prime := range primes {
for j := 0; j < i; j++ {
if prime.Cmp(primes[j]) == 0 {
continue NextSetOfPrimes
}
}
}
n := new(big.Int).Set(bigOne)
totient := new(big.Int).Set(bigOne)
pminus1 := new(big.Int)
for _, prime := range primes {
n.Mul(n, prime)
pminus1.Sub(prime, bigOne)
totient.Mul(totient, pminus1)
}
if n.BitLen() != bits {
// This should never happen for nprimes == 2 because
// crypto/rand should set the top two bits in each prime.
// For nprimes > 2 we hope it does not happen often.
continue NextSetOfPrimes
}
priv.D = new(big.Int)
e := big.NewInt(int64(priv.E))
ok := priv.D.ModInverse(e, totient)
if ok != nil {
priv.Primes = primes
priv.N = n
break
}
}
priv.Precompute()
return priv, nil
}

901
vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go generated vendored Normal file
View File

@@ -0,0 +1,901 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package openpgp
import (
goerrors "errors"
"fmt"
"io"
"time"
"github.com/ProtonMail/go-crypto/openpgp/armor"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/packet"
)
// PublicKeyType is the armor type for a PGP public key.
var PublicKeyType = "PGP PUBLIC KEY BLOCK"
// PrivateKeyType is the armor type for a PGP private key.
var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
// An Entity represents the components of an OpenPGP key: a primary public key
// (which must be a signing key), one or more identities claimed by that key,
// and zero or more subkeys, which may be encryption keys.
type Entity struct {
PrimaryKey *packet.PublicKey
PrivateKey *packet.PrivateKey
Identities map[string]*Identity // indexed by Identity.Name
Revocations []*packet.Signature
Subkeys []Subkey
SelfSignature *packet.Signature // Direct-key self signature of the PrimaryKey (contains primary key properties in v6)
Signatures []*packet.Signature // all (potentially unverified) self-signatures, revocations, and third-party signatures
}
// An Identity represents an identity claimed by an Entity and zero or more
// assertions by other entities about that claim.
type Identity struct {
Name string // by convention, has the form "Full Name (comment) <email@example.com>"
UserId *packet.UserId
SelfSignature *packet.Signature
Revocations []*packet.Signature
Signatures []*packet.Signature // all (potentially unverified) self-signatures, revocations, and third-party signatures
}
// A Subkey is an additional public key in an Entity. Subkeys can be used for
// encryption.
type Subkey struct {
PublicKey *packet.PublicKey
PrivateKey *packet.PrivateKey
Sig *packet.Signature
Revocations []*packet.Signature
}
// A Key identifies a specific public key in an Entity. This is either the
// Entity's primary key or a subkey.
type Key struct {
Entity *Entity
PublicKey *packet.PublicKey
PrivateKey *packet.PrivateKey
SelfSignature *packet.Signature
Revocations []*packet.Signature
}
// A KeyRing provides access to public and private keys.
type KeyRing interface {
// KeysById returns the set of keys that have the given key id.
KeysById(id uint64) []Key
// KeysByIdAndUsage returns the set of keys with the given id
// that also meet the key usage given by requiredUsage.
// The requiredUsage is expressed as the bitwise-OR of
// packet.KeyFlag* values.
KeysByIdUsage(id uint64, requiredUsage byte) []Key
// DecryptionKeys returns all private keys that are valid for
// decryption.
DecryptionKeys() []Key
}
// PrimaryIdentity returns an Identity, preferring non-revoked identities,
// identities marked as primary, or the latest-created identity, in that order.
func (e *Entity) PrimaryIdentity() *Identity {
var primaryIdentity *Identity
for _, ident := range e.Identities {
if shouldPreferIdentity(primaryIdentity, ident) {
primaryIdentity = ident
}
}
return primaryIdentity
}
func shouldPreferIdentity(existingId, potentialNewId *Identity) bool {
if existingId == nil {
return true
}
if len(existingId.Revocations) > len(potentialNewId.Revocations) {
return true
}
if len(existingId.Revocations) < len(potentialNewId.Revocations) {
return false
}
if existingId.SelfSignature == nil {
return true
}
if existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId &&
!(potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId) {
return false
}
if !(existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId) &&
potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId {
return true
}
return potentialNewId.SelfSignature.CreationTime.After(existingId.SelfSignature.CreationTime)
}
// EncryptionKey returns the best candidate Key for encrypting a message to the
// given Entity.
func (e *Entity) EncryptionKey(now time.Time) (Key, bool) {
// Fail to find any encryption key if the...
primarySelfSignature, primaryIdentity := e.PrimarySelfSignature()
if primarySelfSignature == nil || // no self-signature found
e.PrimaryKey.KeyExpired(primarySelfSignature, now) || // primary key has expired
e.Revoked(now) || // primary key has been revoked
primarySelfSignature.SigExpired(now) || // user ID or or direct self-signature has expired
(primaryIdentity != nil && primaryIdentity.Revoked(now)) { // user ID has been revoked (for v4 keys)
return Key{}, false
}
// Iterate the keys to find the newest, unexpired one
candidateSubkey := -1
var maxTime time.Time
for i, subkey := range e.Subkeys {
if subkey.Sig.FlagsValid &&
subkey.Sig.FlagEncryptCommunications &&
subkey.PublicKey.PubKeyAlgo.CanEncrypt() &&
!subkey.PublicKey.KeyExpired(subkey.Sig, now) &&
!subkey.Sig.SigExpired(now) &&
!subkey.Revoked(now) &&
(maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) {
candidateSubkey = i
maxTime = subkey.Sig.CreationTime
}
}
if candidateSubkey != -1 {
subkey := e.Subkeys[candidateSubkey]
return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Revocations}, true
}
// If we don't have any subkeys for encryption and the primary key
// is marked as OK to encrypt with, then we can use it.
if primarySelfSignature.FlagsValid && primarySelfSignature.FlagEncryptCommunications &&
e.PrimaryKey.PubKeyAlgo.CanEncrypt() {
return Key{e, e.PrimaryKey, e.PrivateKey, primarySelfSignature, e.Revocations}, true
}
return Key{}, false
}
// CertificationKey return the best candidate Key for certifying a key with this
// Entity.
func (e *Entity) CertificationKey(now time.Time) (Key, bool) {
return e.CertificationKeyById(now, 0)
}
// CertificationKeyById return the Key for key certification with this
// Entity and keyID.
func (e *Entity) CertificationKeyById(now time.Time, id uint64) (Key, bool) {
return e.signingKeyByIdUsage(now, id, packet.KeyFlagCertify)
}
// SigningKey return the best candidate Key for signing a message with this
// Entity.
func (e *Entity) SigningKey(now time.Time) (Key, bool) {
return e.SigningKeyById(now, 0)
}
// SigningKeyById return the Key for signing a message with this
// Entity and keyID.
func (e *Entity) SigningKeyById(now time.Time, id uint64) (Key, bool) {
return e.signingKeyByIdUsage(now, id, packet.KeyFlagSign)
}
func (e *Entity) signingKeyByIdUsage(now time.Time, id uint64, flags int) (Key, bool) {
// Fail to find any signing key if the...
primarySelfSignature, primaryIdentity := e.PrimarySelfSignature()
if primarySelfSignature == nil || // no self-signature found
e.PrimaryKey.KeyExpired(primarySelfSignature, now) || // primary key has expired
e.Revoked(now) || // primary key has been revoked
primarySelfSignature.SigExpired(now) || // user ID or direct self-signature has expired
(primaryIdentity != nil && primaryIdentity.Revoked(now)) { // user ID has been revoked (for v4 keys)
return Key{}, false
}
// Iterate the keys to find the newest, unexpired one
candidateSubkey := -1
var maxTime time.Time
for idx, subkey := range e.Subkeys {
if subkey.Sig.FlagsValid &&
(flags&packet.KeyFlagCertify == 0 || subkey.Sig.FlagCertify) &&
(flags&packet.KeyFlagSign == 0 || subkey.Sig.FlagSign) &&
subkey.PublicKey.PubKeyAlgo.CanSign() &&
!subkey.PublicKey.KeyExpired(subkey.Sig, now) &&
!subkey.Sig.SigExpired(now) &&
!subkey.Revoked(now) &&
(maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) &&
(id == 0 || subkey.PublicKey.KeyId == id) {
candidateSubkey = idx
maxTime = subkey.Sig.CreationTime
}
}
if candidateSubkey != -1 {
subkey := e.Subkeys[candidateSubkey]
return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Revocations}, true
}
// If we don't have any subkeys for signing and the primary key
// is marked as OK to sign with, then we can use it.
if primarySelfSignature.FlagsValid &&
(flags&packet.KeyFlagCertify == 0 || primarySelfSignature.FlagCertify) &&
(flags&packet.KeyFlagSign == 0 || primarySelfSignature.FlagSign) &&
e.PrimaryKey.PubKeyAlgo.CanSign() &&
(id == 0 || e.PrimaryKey.KeyId == id) {
return Key{e, e.PrimaryKey, e.PrivateKey, primarySelfSignature, e.Revocations}, true
}
// No keys with a valid Signing Flag or no keys matched the id passed in
return Key{}, false
}
func revoked(revocations []*packet.Signature, now time.Time) bool {
for _, revocation := range revocations {
if revocation.RevocationReason != nil && *revocation.RevocationReason == packet.KeyCompromised {
// If the key is compromised, the key is considered revoked even before the revocation date.
return true
}
if !revocation.SigExpired(now) {
return true
}
}
return false
}
// Revoked returns whether the entity has any direct key revocation signatures.
// Note that third-party revocation signatures are not supported.
// Note also that Identity and Subkey revocation should be checked separately.
func (e *Entity) Revoked(now time.Time) bool {
return revoked(e.Revocations, now)
}
// EncryptPrivateKeys encrypts all non-encrypted keys in the entity with the same key
// derived from the provided passphrase. Public keys and dummy keys are ignored,
// and don't cause an error to be returned.
func (e *Entity) EncryptPrivateKeys(passphrase []byte, config *packet.Config) error {
var keysToEncrypt []*packet.PrivateKey
// Add entity private key to encrypt.
if e.PrivateKey != nil && !e.PrivateKey.Dummy() && !e.PrivateKey.Encrypted {
keysToEncrypt = append(keysToEncrypt, e.PrivateKey)
}
// Add subkeys to encrypt.
for _, sub := range e.Subkeys {
if sub.PrivateKey != nil && !sub.PrivateKey.Dummy() && !sub.PrivateKey.Encrypted {
keysToEncrypt = append(keysToEncrypt, sub.PrivateKey)
}
}
return packet.EncryptPrivateKeys(keysToEncrypt, passphrase, config)
}
// DecryptPrivateKeys decrypts all encrypted keys in the entity with the given passphrase.
// Avoids recomputation of similar s2k key derivations. Public keys and dummy keys are ignored,
// and don't cause an error to be returned.
func (e *Entity) DecryptPrivateKeys(passphrase []byte) error {
var keysToDecrypt []*packet.PrivateKey
// Add entity private key to decrypt.
if e.PrivateKey != nil && !e.PrivateKey.Dummy() && e.PrivateKey.Encrypted {
keysToDecrypt = append(keysToDecrypt, e.PrivateKey)
}
// Add subkeys to decrypt.
for _, sub := range e.Subkeys {
if sub.PrivateKey != nil && !sub.PrivateKey.Dummy() && sub.PrivateKey.Encrypted {
keysToDecrypt = append(keysToDecrypt, sub.PrivateKey)
}
}
return packet.DecryptPrivateKeys(keysToDecrypt, passphrase)
}
// Revoked returns whether the identity has been revoked by a self-signature.
// Note that third-party revocation signatures are not supported.
func (i *Identity) Revoked(now time.Time) bool {
return revoked(i.Revocations, now)
}
// Revoked returns whether the subkey has been revoked by a self-signature.
// Note that third-party revocation signatures are not supported.
func (s *Subkey) Revoked(now time.Time) bool {
return revoked(s.Revocations, now)
}
// Revoked returns whether the key or subkey has been revoked by a self-signature.
// Note that third-party revocation signatures are not supported.
// Note also that Identity revocation should be checked separately.
// Normally, it's not necessary to call this function, except on keys returned by
// KeysById or KeysByIdUsage.
func (key *Key) Revoked(now time.Time) bool {
return revoked(key.Revocations, now)
}
// An EntityList contains one or more Entities.
type EntityList []*Entity
// KeysById returns the set of keys that have the given key id.
func (el EntityList) KeysById(id uint64) (keys []Key) {
for _, e := range el {
if e.PrimaryKey.KeyId == id {
selfSig, _ := e.PrimarySelfSignature()
keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig, e.Revocations})
}
for _, subKey := range e.Subkeys {
if subKey.PublicKey.KeyId == id {
keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig, subKey.Revocations})
}
}
}
return
}
// KeysByIdAndUsage returns the set of keys with the given id that also meet
// the key usage given by requiredUsage. The requiredUsage is expressed as
// the bitwise-OR of packet.KeyFlag* values.
func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) {
for _, key := range el.KeysById(id) {
if requiredUsage != 0 {
if key.SelfSignature == nil || !key.SelfSignature.FlagsValid {
continue
}
var usage byte
if key.SelfSignature.FlagCertify {
usage |= packet.KeyFlagCertify
}
if key.SelfSignature.FlagSign {
usage |= packet.KeyFlagSign
}
if key.SelfSignature.FlagEncryptCommunications {
usage |= packet.KeyFlagEncryptCommunications
}
if key.SelfSignature.FlagEncryptStorage {
usage |= packet.KeyFlagEncryptStorage
}
if usage&requiredUsage != requiredUsage {
continue
}
}
keys = append(keys, key)
}
return
}
// DecryptionKeys returns all private keys that are valid for decryption.
func (el EntityList) DecryptionKeys() (keys []Key) {
for _, e := range el {
for _, subKey := range e.Subkeys {
if subKey.PrivateKey != nil && subKey.Sig.FlagsValid && (subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig, subKey.Revocations})
}
}
}
return
}
// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
func ReadArmoredKeyRing(r io.Reader) (EntityList, error) {
block, err := armor.Decode(r)
if err == io.EOF {
return nil, errors.InvalidArgumentError("no armored data found")
}
if err != nil {
return nil, err
}
if block.Type != PublicKeyType && block.Type != PrivateKeyType {
return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type)
}
return ReadKeyRing(block.Body)
}
// ReadKeyRing reads one or more public/private keys. Unsupported keys are
// ignored as long as at least a single valid key is found.
func ReadKeyRing(r io.Reader) (el EntityList, err error) {
packets := packet.NewReader(r)
var lastUnsupportedError error
for {
var e *Entity
e, err = ReadEntity(packets)
if err != nil {
// TODO: warn about skipped unsupported/unreadable keys
if _, ok := err.(errors.UnsupportedError); ok {
lastUnsupportedError = err
err = readToNextPublicKey(packets)
} else if _, ok := err.(errors.StructuralError); ok {
// Skip unreadable, badly-formatted keys
lastUnsupportedError = err
err = readToNextPublicKey(packets)
}
if err == io.EOF {
err = nil
break
}
if err != nil {
el = nil
break
}
} else {
el = append(el, e)
}
}
if len(el) == 0 && err == nil {
err = lastUnsupportedError
}
return
}
// readToNextPublicKey reads packets until the start of the entity and leaves
// the first packet of the new entity in the Reader.
func readToNextPublicKey(packets *packet.Reader) (err error) {
var p packet.Packet
for {
p, err = packets.Next()
if err == io.EOF {
return
} else if err != nil {
if _, ok := err.(errors.UnsupportedError); ok {
continue
}
return
}
if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
packets.Unread(p)
return
}
}
}
// ReadEntity reads an entity (public key, identities, subkeys etc) from the
// given Reader.
func ReadEntity(packets *packet.Reader) (*Entity, error) {
e := new(Entity)
e.Identities = make(map[string]*Identity)
p, err := packets.Next()
if err != nil {
return nil, err
}
var ok bool
if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
packets.Unread(p)
return nil, errors.StructuralError("first packet was not a public/private key")
}
e.PrimaryKey = &e.PrivateKey.PublicKey
}
if !e.PrimaryKey.PubKeyAlgo.CanSign() {
return nil, errors.StructuralError("primary key cannot be used for signatures")
}
var revocations []*packet.Signature
var directSignatures []*packet.Signature
EachPacket:
for {
p, err := packets.Next()
if err == io.EOF {
break
} else if err != nil {
return nil, err
}
switch pkt := p.(type) {
case *packet.UserId:
if err := addUserID(e, packets, pkt); err != nil {
return nil, err
}
case *packet.Signature:
if pkt.SigType == packet.SigTypeKeyRevocation {
revocations = append(revocations, pkt)
} else if pkt.SigType == packet.SigTypeDirectSignature {
directSignatures = append(directSignatures, pkt)
}
// Else, ignoring the signature as it does not follow anything
// we would know to attach it to.
case *packet.PrivateKey:
if !pkt.IsSubkey {
packets.Unread(p)
break EachPacket
}
err = addSubkey(e, packets, &pkt.PublicKey, pkt)
if err != nil {
return nil, err
}
case *packet.PublicKey:
if !pkt.IsSubkey {
packets.Unread(p)
break EachPacket
}
err = addSubkey(e, packets, pkt, nil)
if err != nil {
return nil, err
}
default:
// we ignore unknown packets.
}
}
if len(e.Identities) == 0 && e.PrimaryKey.Version < 6 {
return nil, errors.StructuralError(fmt.Sprintf("v%d entity without any identities", e.PrimaryKey.Version))
}
// An implementation MUST ensure that a valid direct-key signature is present before using a v6 key.
if e.PrimaryKey.Version == 6 {
if len(directSignatures) == 0 {
return nil, errors.StructuralError("v6 entity without a valid direct-key signature")
}
// Select main direct key signature.
var mainDirectKeySelfSignature *packet.Signature
for _, directSignature := range directSignatures {
if directSignature.SigType == packet.SigTypeDirectSignature &&
directSignature.CheckKeyIdOrFingerprint(e.PrimaryKey) &&
(mainDirectKeySelfSignature == nil ||
directSignature.CreationTime.After(mainDirectKeySelfSignature.CreationTime)) {
mainDirectKeySelfSignature = directSignature
}
}
if mainDirectKeySelfSignature == nil {
return nil, errors.StructuralError("no valid direct-key self-signature for v6 primary key found")
}
// Check that the main self-signature is valid.
err = e.PrimaryKey.VerifyDirectKeySignature(mainDirectKeySelfSignature)
if err != nil {
return nil, errors.StructuralError("invalid direct-key self-signature for v6 primary key")
}
e.SelfSignature = mainDirectKeySelfSignature
e.Signatures = directSignatures
}
for _, revocation := range revocations {
err = e.PrimaryKey.VerifyRevocationSignature(revocation)
if err == nil {
e.Revocations = append(e.Revocations, revocation)
} else {
// TODO: RFC 4880 5.2.3.15 defines revocation keys.
return nil, errors.StructuralError("revocation signature signed by alternate key")
}
}
return e, nil
}
func addUserID(e *Entity, packets *packet.Reader, pkt *packet.UserId) error {
// Make a new Identity object, that we might wind up throwing away.
// We'll only add it if we get a valid self-signature over this
// userID.
identity := new(Identity)
identity.Name = pkt.Id
identity.UserId = pkt
for {
p, err := packets.Next()
if err == io.EOF {
break
} else if err != nil {
return err
}
sig, ok := p.(*packet.Signature)
if !ok {
packets.Unread(p)
break
}
if sig.SigType != packet.SigTypeGenericCert &&
sig.SigType != packet.SigTypePersonaCert &&
sig.SigType != packet.SigTypeCasualCert &&
sig.SigType != packet.SigTypePositiveCert &&
sig.SigType != packet.SigTypeCertificationRevocation {
return errors.StructuralError("user ID signature with wrong type")
}
if sig.CheckKeyIdOrFingerprint(e.PrimaryKey) {
if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil {
return errors.StructuralError("user ID self-signature invalid: " + err.Error())
}
if sig.SigType == packet.SigTypeCertificationRevocation {
identity.Revocations = append(identity.Revocations, sig)
} else if identity.SelfSignature == nil || sig.CreationTime.After(identity.SelfSignature.CreationTime) {
identity.SelfSignature = sig
}
identity.Signatures = append(identity.Signatures, sig)
e.Identities[pkt.Id] = identity
} else {
identity.Signatures = append(identity.Signatures, sig)
}
}
return nil
}
func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
var subKey Subkey
subKey.PublicKey = pub
subKey.PrivateKey = priv
for {
p, err := packets.Next()
if err == io.EOF {
break
} else if err != nil {
return errors.StructuralError("subkey signature invalid: " + err.Error())
}
sig, ok := p.(*packet.Signature)
if !ok {
packets.Unread(p)
break
}
if sig.SigType != packet.SigTypeSubkeyBinding && sig.SigType != packet.SigTypeSubkeyRevocation {
return errors.StructuralError("subkey signature with wrong type")
}
if err := e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, sig); err != nil {
return errors.StructuralError("subkey signature invalid: " + err.Error())
}
switch sig.SigType {
case packet.SigTypeSubkeyRevocation:
subKey.Revocations = append(subKey.Revocations, sig)
case packet.SigTypeSubkeyBinding:
if subKey.Sig == nil || sig.CreationTime.After(subKey.Sig.CreationTime) {
subKey.Sig = sig
}
}
}
if subKey.Sig == nil {
return errors.StructuralError("subkey packet not followed by signature")
}
e.Subkeys = append(e.Subkeys, subKey)
return nil
}
// SerializePrivate serializes an Entity, including private key material, but
// excluding signatures from other entities, to the given Writer.
// Identities and subkeys are re-signed in case they changed since NewEntry.
// If config is nil, sensible defaults will be used.
func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) {
if e.PrivateKey.Dummy() {
return errors.ErrDummyPrivateKey("dummy private key cannot re-sign identities")
}
return e.serializePrivate(w, config, true)
}
// SerializePrivateWithoutSigning serializes an Entity, including private key
// material, but excluding signatures from other entities, to the given Writer.
// Self-signatures of identities and subkeys are not re-signed. This is useful
// when serializing GNU dummy keys, among other things.
// If config is nil, sensible defaults will be used.
func (e *Entity) SerializePrivateWithoutSigning(w io.Writer, config *packet.Config) (err error) {
return e.serializePrivate(w, config, false)
}
func (e *Entity) serializePrivate(w io.Writer, config *packet.Config, reSign bool) (err error) {
if e.PrivateKey == nil {
return goerrors.New("openpgp: private key is missing")
}
err = e.PrivateKey.Serialize(w)
if err != nil {
return
}
for _, revocation := range e.Revocations {
err := revocation.Serialize(w)
if err != nil {
return err
}
}
for _, directSignature := range e.Signatures {
err := directSignature.Serialize(w)
if err != nil {
return err
}
}
for _, ident := range e.Identities {
err = ident.UserId.Serialize(w)
if err != nil {
return
}
if reSign {
if ident.SelfSignature == nil {
return goerrors.New("openpgp: can't re-sign identity without valid self-signature")
}
err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config)
if err != nil {
return
}
}
for _, sig := range ident.Signatures {
err = sig.Serialize(w)
if err != nil {
return err
}
}
}
for _, subkey := range e.Subkeys {
err = subkey.PrivateKey.Serialize(w)
if err != nil {
return
}
if reSign {
err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
if err != nil {
return
}
if subkey.Sig.EmbeddedSignature != nil {
err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey,
subkey.PrivateKey, config)
if err != nil {
return
}
}
}
for _, revocation := range subkey.Revocations {
err := revocation.Serialize(w)
if err != nil {
return err
}
}
err = subkey.Sig.Serialize(w)
if err != nil {
return
}
}
return nil
}
// Serialize writes the public part of the given Entity to w, including
// signatures from other entities. No private key material will be output.
func (e *Entity) Serialize(w io.Writer) error {
err := e.PrimaryKey.Serialize(w)
if err != nil {
return err
}
for _, revocation := range e.Revocations {
err := revocation.Serialize(w)
if err != nil {
return err
}
}
for _, directSignature := range e.Signatures {
err := directSignature.Serialize(w)
if err != nil {
return err
}
}
for _, ident := range e.Identities {
err = ident.UserId.Serialize(w)
if err != nil {
return err
}
for _, sig := range ident.Signatures {
err = sig.Serialize(w)
if err != nil {
return err
}
}
}
for _, subkey := range e.Subkeys {
err = subkey.PublicKey.Serialize(w)
if err != nil {
return err
}
for _, revocation := range subkey.Revocations {
err := revocation.Serialize(w)
if err != nil {
return err
}
}
err = subkey.Sig.Serialize(w)
if err != nil {
return err
}
}
return nil
}
// SignIdentity adds a signature to e, from signer, attesting that identity is
// associated with e. The provided identity must already be an element of
// e.Identities and the private key of signer must have been decrypted if
// necessary.
// If config is nil, sensible defaults will be used.
func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error {
certificationKey, ok := signer.CertificationKey(config.Now())
if !ok {
return errors.InvalidArgumentError("no valid certification key found")
}
if certificationKey.PrivateKey.Encrypted {
return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
}
ident, ok := e.Identities[identity]
if !ok {
return errors.InvalidArgumentError("given identity string not found in Entity")
}
sig := createSignaturePacket(certificationKey.PublicKey, packet.SigTypeGenericCert, config)
signingUserID := config.SigningUserId()
if signingUserID != "" {
if _, ok := signer.Identities[signingUserID]; !ok {
return errors.InvalidArgumentError("signer identity string not found in signer Entity")
}
sig.SignerUserId = &signingUserID
}
if err := sig.SignUserId(identity, e.PrimaryKey, certificationKey.PrivateKey, config); err != nil {
return err
}
ident.Signatures = append(ident.Signatures, sig)
return nil
}
// RevokeKey generates a key revocation signature (packet.SigTypeKeyRevocation) with the
// specified reason code and text (RFC4880 section-5.2.3.23).
// If config is nil, sensible defaults will be used.
func (e *Entity) RevokeKey(reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error {
revSig := createSignaturePacket(e.PrimaryKey, packet.SigTypeKeyRevocation, config)
revSig.RevocationReason = &reason
revSig.RevocationReasonText = reasonText
if err := revSig.RevokeKey(e.PrimaryKey, e.PrivateKey, config); err != nil {
return err
}
e.Revocations = append(e.Revocations, revSig)
return nil
}
// RevokeSubkey generates a subkey revocation signature (packet.SigTypeSubkeyRevocation) for
// a subkey with the specified reason code and text (RFC4880 section-5.2.3.23).
// If config is nil, sensible defaults will be used.
func (e *Entity) RevokeSubkey(sk *Subkey, reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error {
if err := e.PrimaryKey.VerifyKeySignature(sk.PublicKey, sk.Sig); err != nil {
return errors.InvalidArgumentError("given subkey is not associated with this key")
}
revSig := createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyRevocation, config)
revSig.RevocationReason = &reason
revSig.RevocationReasonText = reasonText
if err := revSig.RevokeSubkey(sk.PublicKey, e.PrivateKey, config); err != nil {
return err
}
sk.Revocations = append(sk.Revocations, revSig)
return nil
}
func (e *Entity) primaryDirectSignature() *packet.Signature {
return e.SelfSignature
}
// PrimarySelfSignature searches the entity for the self-signature that stores key preferences.
// For V4 keys, returns the self-signature of the primary identity, and the identity.
// For V6 keys, returns the latest valid direct-key self-signature, and no identity (nil).
// This self-signature is to be used to check the key expiration,
// algorithm preferences, and so on.
func (e *Entity) PrimarySelfSignature() (*packet.Signature, *Identity) {
if e.PrimaryKey.Version == 6 {
return e.primaryDirectSignature(), nil
}
primaryIdentity := e.PrimaryIdentity()
if primaryIdentity == nil {
return nil, nil
}
return primaryIdentity.SelfSignature, primaryIdentity
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,67 @@
// Copyright (C) 2019 ProtonTech AG
package packet
import "math/bits"
// CipherSuite contains a combination of Cipher and Mode
type CipherSuite struct {
// The cipher function
Cipher CipherFunction
// The AEAD mode of operation.
Mode AEADMode
}
// AEADConfig collects a number of AEAD parameters along with sensible defaults.
// A nil AEADConfig is valid and results in all default values.
type AEADConfig struct {
// The AEAD mode of operation.
DefaultMode AEADMode
// Amount of octets in each chunk of data
ChunkSize uint64
}
// Mode returns the AEAD mode of operation.
func (conf *AEADConfig) Mode() AEADMode {
// If no preference is specified, OCB is used (which is mandatory to implement).
if conf == nil || conf.DefaultMode == 0 {
return AEADModeOCB
}
mode := conf.DefaultMode
if mode != AEADModeEAX && mode != AEADModeOCB && mode != AEADModeGCM {
panic("AEAD mode unsupported")
}
return mode
}
// ChunkSizeByte returns the byte indicating the chunk size. The effective
// chunk size is computed with the formula uint64(1) << (chunkSizeByte + 6)
// limit chunkSizeByte to 16 which equals to 2^22 = 4 MiB
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2
func (conf *AEADConfig) ChunkSizeByte() byte {
if conf == nil || conf.ChunkSize == 0 {
return 12 // 1 << (12 + 6) == 262144 bytes
}
chunkSize := conf.ChunkSize
exponent := bits.Len64(chunkSize) - 1
switch {
case exponent < 6:
exponent = 6
case exponent > 22:
exponent = 22
}
return byte(exponent - 6)
}
// decodeAEADChunkSize returns the effective chunk size. In 32-bit systems, the
// maximum returned value is 1 << 30.
func decodeAEADChunkSize(c byte) int {
size := uint64(1 << (c + 6))
if size != uint64(int(size)) {
return 1 << 30
}
return int(size)
}

View File

@@ -0,0 +1,250 @@
// Copyright (C) 2019 ProtonTech AG
package packet
import (
"crypto/cipher"
"encoding/binary"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
// aeadCrypter is an AEAD opener/sealer, its configuration, and data for en/decryption.
type aeadCrypter struct {
aead cipher.AEAD
chunkSize int
nonce []byte
associatedData []byte // Chunk-independent associated data
chunkIndex []byte // Chunk counter
packetTag packetType // SEIP packet (v2) or AEAD Encrypted Data packet
bytesProcessed int // Amount of plaintext bytes encrypted/decrypted
}
// computeNonce takes the incremental index and computes an eXclusive OR with
// the least significant 8 bytes of the receivers' initial nonce (see sec.
// 5.16.1 and 5.16.2). It returns the resulting nonce.
func (wo *aeadCrypter) computeNextNonce() (nonce []byte) {
if wo.packetTag == packetTypeSymmetricallyEncryptedIntegrityProtected {
return wo.nonce
}
nonce = make([]byte, len(wo.nonce))
copy(nonce, wo.nonce)
offset := len(wo.nonce) - 8
for i := 0; i < 8; i++ {
nonce[i+offset] ^= wo.chunkIndex[i]
}
return
}
// incrementIndex performs an integer increment by 1 of the integer represented by the
// slice, modifying it accordingly.
func (wo *aeadCrypter) incrementIndex() error {
index := wo.chunkIndex
if len(index) == 0 {
return errors.AEADError("Index has length 0")
}
for i := len(index) - 1; i >= 0; i-- {
if index[i] < 255 {
index[i]++
return nil
}
index[i] = 0
}
return errors.AEADError("cannot further increment index")
}
// aeadDecrypter reads and decrypts bytes. It buffers extra decrypted bytes when
// necessary, similar to aeadEncrypter.
type aeadDecrypter struct {
aeadCrypter // Embedded ciphertext opener
reader io.Reader // 'reader' is a partialLengthReader
chunkBytes []byte
peekedBytes []byte // Used to detect last chunk
buffer []byte // Buffered decrypted bytes
}
// Read decrypts bytes and reads them into dst. It decrypts when necessary and
// buffers extra decrypted bytes. It returns the number of bytes copied into dst
// and an error.
func (ar *aeadDecrypter) Read(dst []byte) (n int, err error) {
// Return buffered plaintext bytes from previous calls
if len(ar.buffer) > 0 {
n = copy(dst, ar.buffer)
ar.buffer = ar.buffer[n:]
return
}
// Read a chunk
tagLen := ar.aead.Overhead()
copy(ar.chunkBytes, ar.peekedBytes) // Copy bytes peeked in previous chunk or in initialization
bytesRead, errRead := io.ReadFull(ar.reader, ar.chunkBytes[tagLen:])
if errRead != nil && errRead != io.EOF && errRead != io.ErrUnexpectedEOF {
return 0, errRead
}
if bytesRead > 0 {
ar.peekedBytes = ar.chunkBytes[bytesRead:bytesRead+tagLen]
decrypted, errChunk := ar.openChunk(ar.chunkBytes[:bytesRead])
if errChunk != nil {
return 0, errChunk
}
// Return decrypted bytes, buffering if necessary
n = copy(dst, decrypted)
ar.buffer = decrypted[n:]
return
}
return 0, io.EOF
}
// Close checks the final authentication tag of the stream.
// In the future, this function could also be used to wipe the reader
// and peeked & decrypted bytes, if necessary.
func (ar *aeadDecrypter) Close() (err error) {
errChunk := ar.validateFinalTag(ar.peekedBytes)
if errChunk != nil {
return errChunk
}
return nil
}
// openChunk decrypts and checks integrity of an encrypted chunk, returning
// the underlying plaintext and an error. It accesses peeked bytes from next
// chunk, to identify the last chunk and decrypt/validate accordingly.
func (ar *aeadDecrypter) openChunk(data []byte) ([]byte, error) {
adata := ar.associatedData
if ar.aeadCrypter.packetTag == packetTypeAEADEncrypted {
adata = append(ar.associatedData, ar.chunkIndex...)
}
nonce := ar.computeNextNonce()
plainChunk, err := ar.aead.Open(data[:0:len(data)], nonce, data, adata)
if err != nil {
return nil, errors.ErrAEADTagVerification
}
ar.bytesProcessed += len(plainChunk)
if err = ar.aeadCrypter.incrementIndex(); err != nil {
return nil, err
}
return plainChunk, nil
}
// Checks the summary tag. It takes into account the total decrypted bytes into
// the associated data. It returns an error, or nil if the tag is valid.
func (ar *aeadDecrypter) validateFinalTag(tag []byte) error {
// Associated: tag, version, cipher, aead, chunk size, ...
amountBytes := make([]byte, 8)
binary.BigEndian.PutUint64(amountBytes, uint64(ar.bytesProcessed))
adata := ar.associatedData
if ar.aeadCrypter.packetTag == packetTypeAEADEncrypted {
// ... index ...
adata = append(ar.associatedData, ar.chunkIndex...)
}
// ... and total number of encrypted octets
adata = append(adata, amountBytes...)
nonce := ar.computeNextNonce()
if _, err := ar.aead.Open(nil, nonce, tag, adata); err != nil {
return errors.ErrAEADTagVerification
}
return nil
}
// aeadEncrypter encrypts and writes bytes. It encrypts when necessary according
// to the AEAD block size, and buffers the extra encrypted bytes for next write.
type aeadEncrypter struct {
aeadCrypter // Embedded plaintext sealer
writer io.WriteCloser // 'writer' is a partialLengthWriter
chunkBytes []byte
offset int
}
// Write encrypts and writes bytes. It encrypts when necessary and buffers extra
// plaintext bytes for next call. When the stream is finished, Close() MUST be
// called to append the final tag.
func (aw *aeadEncrypter) Write(plaintextBytes []byte) (n int, err error) {
for n != len(plaintextBytes) {
copied := copy(aw.chunkBytes[aw.offset:aw.chunkSize], plaintextBytes[n:])
n += copied
aw.offset += copied
if aw.offset == aw.chunkSize {
encryptedChunk, err := aw.sealChunk(aw.chunkBytes[:aw.offset])
if err != nil {
return n, err
}
_, err = aw.writer.Write(encryptedChunk)
if err != nil {
return n, err
}
aw.offset = 0
}
}
return
}
// Close encrypts and writes the remaining buffered plaintext if any, appends
// the final authentication tag, and closes the embedded writer. This function
// MUST be called at the end of a stream.
func (aw *aeadEncrypter) Close() (err error) {
// Encrypt and write a chunk if there's buffered data left, or if we haven't
// written any chunks yet.
if aw.offset > 0 || aw.bytesProcessed == 0 {
lastEncryptedChunk, err := aw.sealChunk(aw.chunkBytes[:aw.offset])
if err != nil {
return err
}
_, err = aw.writer.Write(lastEncryptedChunk)
if err != nil {
return err
}
}
// Compute final tag (associated data: packet tag, version, cipher, aead,
// chunk size...
adata := aw.associatedData
if aw.aeadCrypter.packetTag == packetTypeAEADEncrypted {
// ... index ...
adata = append(aw.associatedData, aw.chunkIndex...)
}
// ... and total number of encrypted octets
amountBytes := make([]byte, 8)
binary.BigEndian.PutUint64(amountBytes, uint64(aw.bytesProcessed))
adata = append(adata, amountBytes...)
nonce := aw.computeNextNonce()
finalTag := aw.aead.Seal(nil, nonce, nil, adata)
_, err = aw.writer.Write(finalTag)
if err != nil {
return err
}
return aw.writer.Close()
}
// sealChunk Encrypts and authenticates the given chunk.
func (aw *aeadEncrypter) sealChunk(data []byte) ([]byte, error) {
if len(data) > aw.chunkSize {
return nil, errors.AEADError("chunk exceeds maximum length")
}
if aw.associatedData == nil {
return nil, errors.AEADError("can't seal without headers")
}
adata := aw.associatedData
if aw.aeadCrypter.packetTag == packetTypeAEADEncrypted {
adata = append(aw.associatedData, aw.chunkIndex...)
}
nonce := aw.computeNextNonce()
encrypted := aw.aead.Seal(data[:0], nonce, data, adata)
aw.bytesProcessed += len(data)
if err := aw.aeadCrypter.incrementIndex(); err != nil {
return nil, err
}
return encrypted, nil
}

View File

@@ -0,0 +1,100 @@
// Copyright (C) 2019 ProtonTech AG
package packet
import (
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
)
// AEADEncrypted represents an AEAD Encrypted Packet.
// See https://www.ietf.org/archive/id/draft-koch-openpgp-2015-rfc4880bis-00.html#name-aead-encrypted-data-packet-t
type AEADEncrypted struct {
cipher CipherFunction
mode AEADMode
chunkSizeByte byte
Contents io.Reader // Encrypted chunks and tags
initialNonce []byte // Referred to as IV in RFC4880-bis
}
// Only currently defined version
const aeadEncryptedVersion = 1
func (ae *AEADEncrypted) parse(buf io.Reader) error {
headerData := make([]byte, 4)
if n, err := io.ReadFull(buf, headerData); n < 4 {
return errors.AEADError("could not read aead header:" + err.Error())
}
// Read initial nonce
mode := AEADMode(headerData[2])
nonceLen := mode.IvLength()
// This packet supports only EAX and OCB
// https://www.ietf.org/archive/id/draft-koch-openpgp-2015-rfc4880bis-00.html#name-aead-encrypted-data-packet-t
if nonceLen == 0 || mode > AEADModeOCB {
return errors.AEADError("unknown mode")
}
initialNonce := make([]byte, nonceLen)
if n, err := io.ReadFull(buf, initialNonce); n < nonceLen {
return errors.AEADError("could not read aead nonce:" + err.Error())
}
ae.Contents = buf
ae.initialNonce = initialNonce
c := headerData[1]
if _, ok := algorithm.CipherById[c]; !ok {
return errors.UnsupportedError("unknown cipher: " + string(c))
}
ae.cipher = CipherFunction(c)
ae.mode = mode
ae.chunkSizeByte = headerData[3]
return nil
}
// Decrypt returns a io.ReadCloser from which decrypted bytes can be read, or
// an error.
func (ae *AEADEncrypted) Decrypt(ciph CipherFunction, key []byte) (io.ReadCloser, error) {
return ae.decrypt(key)
}
// decrypt prepares an aeadCrypter and returns a ReadCloser from which
// decrypted bytes can be read (see aeadDecrypter.Read()).
func (ae *AEADEncrypted) decrypt(key []byte) (io.ReadCloser, error) {
blockCipher := ae.cipher.new(key)
aead := ae.mode.new(blockCipher)
// Carry the first tagLen bytes
chunkSize := decodeAEADChunkSize(ae.chunkSizeByte)
tagLen := ae.mode.TagLength()
chunkBytes := make([]byte, chunkSize+tagLen*2)
peekedBytes := chunkBytes[chunkSize+tagLen:]
n, err := io.ReadFull(ae.Contents, peekedBytes)
if n < tagLen || (err != nil && err != io.EOF) {
return nil, errors.AEADError("Not enough data to decrypt:" + err.Error())
}
return &aeadDecrypter{
aeadCrypter: aeadCrypter{
aead: aead,
chunkSize: chunkSize,
nonce: ae.initialNonce,
associatedData: ae.associatedData(),
chunkIndex: make([]byte, 8),
packetTag: packetTypeAEADEncrypted,
},
reader: ae.Contents,
chunkBytes: chunkBytes,
peekedBytes: peekedBytes,
}, nil
}
// associatedData for chunks: tag, version, cipher, mode, chunk size byte
func (ae *AEADEncrypted) associatedData() []byte {
return []byte{
0xD4,
aeadEncryptedVersion,
byte(ae.cipher),
byte(ae.mode),
ae.chunkSizeByte}
}

View File

@@ -0,0 +1,192 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"compress/bzip2"
"compress/flate"
"compress/zlib"
"io"
"strconv"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
// Compressed represents a compressed OpenPGP packet. The decompressed contents
// will contain more OpenPGP packets. See RFC 4880, section 5.6.
type Compressed struct {
Body io.Reader
}
const (
NoCompression = flate.NoCompression
BestSpeed = flate.BestSpeed
BestCompression = flate.BestCompression
DefaultCompression = flate.DefaultCompression
)
// CompressionConfig contains compressor configuration settings.
type CompressionConfig struct {
// Level is the compression level to use. It must be set to
// between -1 and 9, with -1 causing the compressor to use the
// default compression level, 0 causing the compressor to use
// no compression and 1 to 9 representing increasing (better,
// slower) compression levels. If Level is less than -1 or
// more then 9, a non-nil error will be returned during
// encryption. See the constants above for convenient common
// settings for Level.
Level int
}
// decompressionReader ensures that the whole compression packet is read.
type decompressionReader struct {
compressed io.Reader
decompressed io.ReadCloser
readAll bool
}
func newDecompressionReader(r io.Reader, decompressor io.ReadCloser) *decompressionReader {
return &decompressionReader{
compressed: r,
decompressed: decompressor,
}
}
func (dr *decompressionReader) Read(data []byte) (n int, err error) {
if dr.readAll {
return 0, io.EOF
}
n, err = dr.decompressed.Read(data)
if err == io.EOF {
dr.readAll = true
// Close the decompressor.
if errDec := dr.decompressed.Close(); errDec != nil {
return n, errDec
}
// Consume all remaining data from the compressed packet.
consumeAll(dr.compressed)
}
return n, err
}
func (c *Compressed) parse(r io.Reader) error {
var buf [1]byte
_, err := readFull(r, buf[:])
if err != nil {
return err
}
switch buf[0] {
case 0:
c.Body = r
case 1:
c.Body = newDecompressionReader(r, flate.NewReader(r))
case 2:
decompressor, err := zlib.NewReader(r)
if err != nil {
return err
}
c.Body = newDecompressionReader(r, decompressor)
case 3:
c.Body = newDecompressionReader(r, io.NopCloser(bzip2.NewReader(r)))
default:
err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
}
return err
}
// LimitedBodyReader wraps the provided body reader with a limiter that restricts
// the number of bytes read to the specified limit.
// If limit is nil, the reader is unbounded.
func (c *Compressed) LimitedBodyReader(limit *int64) io.Reader {
if limit == nil {
return c.Body
}
return &LimitReader{R: c.Body, N: *limit}
}
// compressedWriterCloser represents the serialized compression stream
// header and the compressor. Its Close() method ensures that both the
// compressor and serialized stream header are closed. Its Write()
// method writes to the compressor.
type compressedWriteCloser struct {
sh io.Closer // Stream Header
c io.WriteCloser // Compressor
}
func (cwc compressedWriteCloser) Write(p []byte) (int, error) {
return cwc.c.Write(p)
}
func (cwc compressedWriteCloser) Close() (err error) {
err = cwc.c.Close()
if err != nil {
return err
}
return cwc.sh.Close()
}
// SerializeCompressed serializes a compressed data packet to w and
// returns a WriteCloser to which the literal data packets themselves
// can be written and which MUST be closed on completion. If cc is
// nil, sensible defaults will be used to configure the compression
// algorithm.
func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) {
compressed, err := serializeStreamHeader(w, packetTypeCompressed)
if err != nil {
return
}
_, err = compressed.Write([]byte{uint8(algo)})
if err != nil {
return
}
level := DefaultCompression
if cc != nil {
level = cc.Level
}
var compressor io.WriteCloser
switch algo {
case CompressionZIP:
compressor, err = flate.NewWriter(compressed, level)
case CompressionZLIB:
compressor, err = zlib.NewWriterLevel(compressed, level)
default:
s := strconv.Itoa(int(algo))
err = errors.UnsupportedError("Unsupported compression algorithm: " + s)
}
if err != nil {
return
}
literaldata = compressedWriteCloser{compressed, compressor}
return
}
// LimitReader is an io.Reader that fails with MessageToLarge if read bytes exceed N.
type LimitReader struct {
R io.Reader // underlying reader
N int64 // max bytes allowed
}
func (l *LimitReader) Read(p []byte) (int, error) {
if l.N <= 0 {
return 0, errors.ErrMessageTooLarge
}
n, err := l.R.Read(p)
l.N -= int64(n)
if err == nil && l.N <= 0 {
err = errors.ErrMessageTooLarge
}
return n, err
}

View File

@@ -0,0 +1,434 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"crypto"
"crypto/rand"
"io"
"math/big"
"time"
"github.com/ProtonMail/go-crypto/openpgp/s2k"
)
var (
defaultRejectPublicKeyAlgorithms = map[PublicKeyAlgorithm]bool{
PubKeyAlgoElGamal: true,
PubKeyAlgoDSA: true,
}
defaultRejectHashAlgorithms = map[crypto.Hash]bool{
crypto.MD5: true,
crypto.RIPEMD160: true,
}
defaultRejectMessageHashAlgorithms = map[crypto.Hash]bool{
crypto.SHA1: true,
crypto.MD5: true,
crypto.RIPEMD160: true,
}
defaultRejectCurves = map[Curve]bool{
CurveSecP256k1: true,
}
)
// A global feature flag to indicate v5 support.
// Can be set via a build tag, e.g.: `go build -tags v5 ./...`
// If the build tag is missing config_v5.go will set it to true.
//
// Disables parsing of v5 keys and v5 signatures.
// These are non-standard entities, which in the crypto-refresh have been superseded
// by v6 keys, v6 signatures and SEIPDv2 encrypted data, respectively.
var V5Disabled = false
// Config collects a number of parameters along with sensible defaults.
// A nil *Config is valid and results in all default values.
type Config struct {
// Rand provides the source of entropy.
// If nil, the crypto/rand Reader is used.
Rand io.Reader
// DefaultHash is the default hash function to be used.
// If zero, SHA-256 is used.
DefaultHash crypto.Hash
// DefaultCipher is the cipher to be used.
// If zero, AES-128 is used.
DefaultCipher CipherFunction
// Time returns the current time as the number of seconds since the
// epoch. If Time is nil, time.Now is used.
Time func() time.Time
// DefaultCompressionAlgo is the compression algorithm to be
// applied to the plaintext before encryption. If zero, no
// compression is done.
DefaultCompressionAlgo CompressionAlgo
// CompressionConfig configures the compression settings.
CompressionConfig *CompressionConfig
// S2K (String to Key) config, used for key derivation in the context of secret key encryption
// and password-encrypted data.
// If nil, the default configuration is used
S2KConfig *s2k.Config
// Iteration count for Iterated S2K (String to Key).
// Only used if sk2.Mode is nil.
// This value is duplicated here from s2k.Config for backwards compatibility.
// It determines the strength of the passphrase stretching when
// the said passphrase is hashed to produce a key. S2KCount
// should be between 65536 and 65011712, inclusive. If Config
// is nil or S2KCount is 0, the value 16777216 used. Not all
// values in the above range can be represented. S2KCount will
// be rounded up to the next representable value if it cannot
// be encoded exactly. When set, it is strongly encrouraged to
// use a value that is at least 65536. See RFC 4880 Section
// 3.7.1.3.
//
// Deprecated: SK2Count should be configured in S2KConfig instead.
S2KCount int
// RSABits is the number of bits in new RSA keys made with NewEntity.
// If zero, then 2048 bit keys are created.
RSABits int
// The public key algorithm to use - will always create a signing primary
// key and encryption subkey.
Algorithm PublicKeyAlgorithm
// Some known primes that are optionally prepopulated by the caller
RSAPrimes []*big.Int
// Curve configures the desired packet.Curve if the Algorithm is PubKeyAlgoECDSA,
// PubKeyAlgoEdDSA, or PubKeyAlgoECDH. If empty Curve25519 is used.
Curve Curve
// AEADConfig configures the use of the new AEAD Encrypted Data Packet,
// defined in the draft of the next version of the OpenPGP specification.
// If a non-nil AEADConfig is passed, usage of this packet is enabled. By
// default, it is disabled. See the documentation of AEADConfig for more
// configuration options related to AEAD.
// **Note: using this option may break compatibility with other OpenPGP
// implementations, as well as future versions of this library.**
AEADConfig *AEADConfig
// V6Keys configures version 6 key generation. If false, this package still
// supports version 6 keys, but produces version 4 keys.
V6Keys bool
// Minimum RSA key size allowed for key generation and message signing, verification and encryption.
MinRSABits uint16
// Reject insecure algorithms, only works with v2 api
RejectPublicKeyAlgorithms map[PublicKeyAlgorithm]bool
RejectHashAlgorithms map[crypto.Hash]bool
RejectMessageHashAlgorithms map[crypto.Hash]bool
RejectCurves map[Curve]bool
// "The validity period of the key. This is the number of seconds after
// the key creation time that the key expires. If this is not present
// or has a value of zero, the key never expires. This is found only on
// a self-signature.""
// https://tools.ietf.org/html/rfc4880#section-5.2.3.6
KeyLifetimeSecs uint32
// "The validity period of the signature. This is the number of seconds
// after the signature creation time that the signature expires. If
// this is not present or has a value of zero, it never expires."
// https://tools.ietf.org/html/rfc4880#section-5.2.3.10
SigLifetimeSecs uint32
// SigningKeyId is used to specify the signing key to use (by Key ID).
// By default, the signing key is selected automatically, preferring
// signing subkeys if available.
SigningKeyId uint64
// SigningIdentity is used to specify a user ID (packet Signer's User ID, type 28)
// when producing a generic certification signature onto an existing user ID.
// The identity must be present in the signer Entity.
SigningIdentity string
// InsecureAllowUnauthenticatedMessages controls, whether it is tolerated to read
// encrypted messages without Modification Detection Code (MDC).
// MDC is mandated by the IETF OpenPGP Crypto Refresh draft and has long been implemented
// in most OpenPGP implementations. Messages without MDC are considered unnecessarily
// insecure and should be prevented whenever possible.
// In case one needs to deal with messages from very old OpenPGP implementations, there
// might be no other way than to tolerate the missing MDC. Setting this flag, allows this
// mode of operation. It should be considered a measure of last resort.
InsecureAllowUnauthenticatedMessages bool
// InsecureAllowDecryptionWithSigningKeys allows decryption with keys marked as signing keys in the v2 API.
// This setting is potentially insecure, but it is needed as some libraries
// ignored key flags when selecting a key for encryption.
// Not relevant for the v1 API, as all keys were allowed in decryption.
InsecureAllowDecryptionWithSigningKeys bool
// KnownNotations is a map of Notation Data names to bools, which controls
// the notation names that are allowed to be present in critical Notation Data
// signature subpackets.
KnownNotations map[string]bool
// SignatureNotations is a list of Notations to be added to any signatures.
SignatureNotations []*Notation
// CheckIntendedRecipients controls, whether the OpenPGP Intended Recipient Fingerprint feature
// should be enabled for encryption and decryption.
// (See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-intended-recipient-fingerpr).
// When the flag is set, encryption produces Intended Recipient Fingerprint signature sub-packets and decryption
// checks whether the key it was encrypted to is one of the included fingerprints in the signature.
// If the flag is disabled, no Intended Recipient Fingerprint sub-packets are created or checked.
// The default behavior, when the config or flag is nil, is to enable the feature.
CheckIntendedRecipients *bool
// CacheSessionKey controls if decryption should return the session key used for decryption.
// If the flag is set, the session key is cached in the message details struct.
CacheSessionKey bool
// CheckPacketSequence is a flag that controls if the pgp message reader should strictly check
// that the packet sequence conforms with the grammar mandated by rfc4880.
// The default behavior, when the config or flag is nil, is to check the packet sequence.
CheckPacketSequence *bool
// NonDeterministicSignaturesViaNotation is a flag to enable randomization of signatures.
// If true, a salt notation is used to randomize signatures generated by v4 and v5 keys
// (v6 signatures are always non-deterministic, by design).
// This protects EdDSA signatures from potentially leaking the secret key in case of faults (i.e. bitflips) which, in principle, could occur
// during the signing computation. It is added to signatures of any algo for simplicity, and as it may also serve as protection in case of
// weaknesses in the hash algo, potentially hindering e.g. some chosen-prefix attacks.
// The default behavior, when the config or flag is nil, is to enable the feature.
NonDeterministicSignaturesViaNotation *bool
// InsecureAllowAllKeyFlagsWhenMissing determines how a key without valid key flags is handled.
// When set to true, a key without flags is treated as if all flags are enabled.
// This behavior is consistent with GPG.
InsecureAllowAllKeyFlagsWhenMissing bool
// MaxDecompressedMessageSize specifies the maximum number of bytes that can be
// read from a compressed packet. This serves as an upper limit to prevent
// excessively large decompressed messages.
MaxDecompressedMessageSize *int64
}
func (c *Config) Random() io.Reader {
if c == nil || c.Rand == nil {
return rand.Reader
}
return c.Rand
}
func (c *Config) Hash() crypto.Hash {
if c == nil || uint(c.DefaultHash) == 0 {
return crypto.SHA256
}
return c.DefaultHash
}
func (c *Config) Cipher() CipherFunction {
if c == nil || uint8(c.DefaultCipher) == 0 {
return CipherAES128
}
return c.DefaultCipher
}
func (c *Config) Now() time.Time {
if c == nil || c.Time == nil {
return time.Now().Truncate(time.Second)
}
return c.Time().Truncate(time.Second)
}
// KeyLifetime returns the validity period of the key.
func (c *Config) KeyLifetime() uint32 {
if c == nil {
return 0
}
return c.KeyLifetimeSecs
}
// SigLifetime returns the validity period of the signature.
func (c *Config) SigLifetime() uint32 {
if c == nil {
return 0
}
return c.SigLifetimeSecs
}
func (c *Config) Compression() CompressionAlgo {
if c == nil {
return CompressionNone
}
return c.DefaultCompressionAlgo
}
func (c *Config) RSAModulusBits() int {
if c == nil || c.RSABits == 0 {
return 2048
}
return c.RSABits
}
func (c *Config) PublicKeyAlgorithm() PublicKeyAlgorithm {
if c == nil || c.Algorithm == 0 {
return PubKeyAlgoRSA
}
return c.Algorithm
}
func (c *Config) CurveName() Curve {
if c == nil || c.Curve == "" {
return Curve25519
}
return c.Curve
}
// Deprecated: The hash iterations should now be queried via the S2K() method.
func (c *Config) PasswordHashIterations() int {
if c == nil || c.S2KCount == 0 {
return 0
}
return c.S2KCount
}
func (c *Config) S2K() *s2k.Config {
if c == nil {
return nil
}
// for backwards compatibility
if c.S2KCount > 0 && c.S2KConfig == nil {
return &s2k.Config{
S2KCount: c.S2KCount,
}
}
return c.S2KConfig
}
func (c *Config) AEAD() *AEADConfig {
if c == nil {
return nil
}
return c.AEADConfig
}
func (c *Config) SigningKey() uint64 {
if c == nil {
return 0
}
return c.SigningKeyId
}
func (c *Config) SigningUserId() string {
if c == nil {
return ""
}
return c.SigningIdentity
}
func (c *Config) AllowUnauthenticatedMessages() bool {
if c == nil {
return false
}
return c.InsecureAllowUnauthenticatedMessages
}
func (c *Config) AllowDecryptionWithSigningKeys() bool {
if c == nil {
return false
}
return c.InsecureAllowDecryptionWithSigningKeys
}
func (c *Config) KnownNotation(notationName string) bool {
if c == nil {
return false
}
return c.KnownNotations[notationName]
}
func (c *Config) Notations() []*Notation {
if c == nil {
return nil
}
return c.SignatureNotations
}
func (c *Config) V6() bool {
if c == nil {
return false
}
return c.V6Keys
}
func (c *Config) IntendedRecipients() bool {
if c == nil || c.CheckIntendedRecipients == nil {
return true
}
return *c.CheckIntendedRecipients
}
func (c *Config) RetrieveSessionKey() bool {
if c == nil {
return false
}
return c.CacheSessionKey
}
func (c *Config) MinimumRSABits() uint16 {
if c == nil || c.MinRSABits == 0 {
return 2047
}
return c.MinRSABits
}
func (c *Config) RejectPublicKeyAlgorithm(alg PublicKeyAlgorithm) bool {
var rejectedAlgorithms map[PublicKeyAlgorithm]bool
if c == nil || c.RejectPublicKeyAlgorithms == nil {
// Default
rejectedAlgorithms = defaultRejectPublicKeyAlgorithms
} else {
rejectedAlgorithms = c.RejectPublicKeyAlgorithms
}
return rejectedAlgorithms[alg]
}
func (c *Config) RejectHashAlgorithm(hash crypto.Hash) bool {
var rejectedAlgorithms map[crypto.Hash]bool
if c == nil || c.RejectHashAlgorithms == nil {
// Default
rejectedAlgorithms = defaultRejectHashAlgorithms
} else {
rejectedAlgorithms = c.RejectHashAlgorithms
}
return rejectedAlgorithms[hash]
}
func (c *Config) RejectMessageHashAlgorithm(hash crypto.Hash) bool {
var rejectedAlgorithms map[crypto.Hash]bool
if c == nil || c.RejectMessageHashAlgorithms == nil {
// Default
rejectedAlgorithms = defaultRejectMessageHashAlgorithms
} else {
rejectedAlgorithms = c.RejectMessageHashAlgorithms
}
return rejectedAlgorithms[hash]
}
func (c *Config) RejectCurve(curve Curve) bool {
var rejectedCurve map[Curve]bool
if c == nil || c.RejectCurves == nil {
// Default
rejectedCurve = defaultRejectCurves
} else {
rejectedCurve = c.RejectCurves
}
return rejectedCurve[curve]
}
func (c *Config) StrictPacketSequence() bool {
if c == nil || c.CheckPacketSequence == nil {
return true
}
return *c.CheckPacketSequence
}
func (c *Config) RandomizeSignaturesViaNotation() bool {
if c == nil || c.NonDeterministicSignaturesViaNotation == nil {
return true
}
return *c.NonDeterministicSignaturesViaNotation
}
func (c *Config) AllowAllKeyFlagsWhenMissing() bool {
if c == nil {
return false
}
return c.InsecureAllowAllKeyFlagsWhenMissing
}
func (c *Config) DecompressedMessageSizeLimit() *int64 {
if c == nil {
return nil
}
return c.MaxDecompressedMessageSize
}
// BoolPointer is a helper function to set a boolean pointer in the Config.
// e.g., config.CheckPacketSequence = BoolPointer(true)
func BoolPointer(value bool) *bool {
return &value
}

Some files were not shown because too many files have changed in this diff Show More