mirror of
https://github.com/cheat/cheat.git
synced 2026-03-07 03:03:32 +01:00
chore: modernize CI and update Go toolchain
- Bump Go from 1.19 to 1.26 and update all dependencies - Rewrite CI workflow with matrix strategy (Linux, macOS, Windows) - Update GitHub Actions to current versions (checkout@v4, setup-go@v5) - Update CodeQL actions from v1 to v3 - Fix cross-platform bug in mock/path.go (path.Join -> filepath.Join) - Clean up dependabot config (weekly schedule, remove stale ignore) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
6
.github/dependabot.yml
vendored
6
.github/dependabot.yml
vendored
@@ -3,9 +3,5 @@ updates:
|
||||
- package-ecosystem: gomod
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 10
|
||||
ignore:
|
||||
- dependency-name: github.com/alecthomas/chroma
|
||||
versions:
|
||||
- 0.9.1
|
||||
|
||||
54
.github/workflows/build.yml
vendored
54
.github/workflows/build.yml
vendored
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: Go
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -8,39 +8,33 @@ on:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
# TODO: is it possible to DRY out these jobs? Aside from `runs-on`, they are
|
||||
# identical.
|
||||
# See: https://github.com/actions/runner/issues/1182
|
||||
build-linux:
|
||||
runs-on: [ubuntu-latest]
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.19
|
||||
- name: Set up Revive (linter)
|
||||
run: go get -u github.com/boyter/scc github.com/mgechev/revive
|
||||
env:
|
||||
GO111MODULE: "off"
|
||||
- name: Build
|
||||
run: make build
|
||||
- name: Test
|
||||
run: make test
|
||||
go-version: stable
|
||||
- name: Install revive
|
||||
run: go install github.com/mgechev/revive@latest
|
||||
- name: Lint
|
||||
run: revive -exclude vendor/... ./...
|
||||
- name: Vet
|
||||
run: go vet ./...
|
||||
- name: Check formatting
|
||||
run: test -z "$(gofmt -l . | grep -v vendor/)"
|
||||
|
||||
build-osx:
|
||||
runs-on: [macos-latest]
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.19
|
||||
- name: Set up Revive (linter)
|
||||
run: go get -u github.com/boyter/scc github.com/mgechev/revive
|
||||
env:
|
||||
GO111MODULE: "off"
|
||||
go-version: stable
|
||||
- name: Build
|
||||
run: make build
|
||||
run: go build -mod vendor ./cmd/cheat
|
||||
- name: Test
|
||||
run: make test
|
||||
run: go test ./...
|
||||
|
||||
8
.github/workflows/codeql-analysis.yml
vendored
8
.github/workflows/codeql-analysis.yml
vendored
@@ -19,12 +19,12 @@ jobs:
|
||||
language: [go]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
39
go.mod
39
go.mod
@@ -1,38 +1,37 @@
|
||||
module github.com/cheat/cheat
|
||||
|
||||
go 1.19
|
||||
go 1.26
|
||||
|
||||
require (
|
||||
github.com/alecthomas/chroma/v2 v2.12.0
|
||||
github.com/alecthomas/chroma/v2 v2.23.1
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
|
||||
github.com/go-git/go-git/v5 v5.11.0
|
||||
github.com/go-git/go-git/v5 v5.16.5
|
||||
github.com/mattn/go-isatty v0.0.20
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||
dario.cat/mergo v1.0.2 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
||||
github.com/cloudflare/circl v1.6.3 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
||||
github.com/dlclark/regexp2 v1.11.5 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/go-git/go-billy/v5 v5.7.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/sergi/go-diff v1.3.1 // indirect
|
||||
github.com/skeema/knownhosts v1.2.1 // indirect
|
||||
github.com/kevinburke/ssh_config v1.5.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
||||
github.com/sergi/go-diff v1.4.0 // indirect
|
||||
github.com/skeema/knownhosts v1.3.2 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
golang.org/x/crypto v0.17.0 // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/tools v0.16.1 // indirect
|
||||
golang.org/x/crypto v0.48.0 // indirect
|
||||
golang.org/x/net v0.50.0 // indirect
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
)
|
||||
|
||||
152
go.sum
152
go.sum
@@ -1,140 +1,118 @@
|
||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
|
||||
github.com/alecthomas/chroma/v2 v2.12.0 h1:Wh8qLEgMMsN7mgyG8/qIpegky2Hvzr4By6gEF7cmWgw=
|
||||
github.com/alecthomas/chroma/v2 v2.12.0/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurGF0EpseFXdKMBw=
|
||||
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
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/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY=
|
||||
github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o=
|
||||
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
|
||||
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
|
||||
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
|
||||
github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
|
||||
github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
|
||||
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
|
||||
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
||||
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
|
||||
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
|
||||
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
|
||||
github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM=
|
||||
github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
|
||||
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s=
|
||||
github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kevinburke/ssh_config v1.5.0 h1:3cPZmE54xb5j3G5xQCjSvokqNwU2uW+3ry1+PRLSPpA=
|
||||
github.com/kevinburke/ssh_config v1.5.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||
github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0=
|
||||
github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
|
||||
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
|
||||
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
|
||||
github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg=
|
||||
github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
|
||||
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
|
||||
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
||||
@@ -3,7 +3,6 @@ package mock
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
@@ -16,7 +15,7 @@ func Path(filename string) string {
|
||||
|
||||
// compute the mock path
|
||||
file, err := filepath.Abs(
|
||||
path.Join(
|
||||
filepath.Join(
|
||||
filepath.Dir(thisfile),
|
||||
"../../mocks",
|
||||
filename,
|
||||
|
||||
3
vendor/dario.cat/mergo/.gitignore
vendored
3
vendor/dario.cat/mergo/.gitignore
vendored
@@ -13,6 +13,9 @@
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Golang/Intellij
|
||||
.idea
|
||||
|
||||
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
||||
.glide/
|
||||
|
||||
|
||||
7
vendor/dario.cat/mergo/FUNDING.json
vendored
Normal file
7
vendor/dario.cat/mergo/FUNDING.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"drips": {
|
||||
"ethereum": {
|
||||
"ownedBy": "0x6160020e7102237aC41bdb156e94401692D76930"
|
||||
}
|
||||
}
|
||||
}
|
||||
105
vendor/dario.cat/mergo/README.md
vendored
105
vendor/dario.cat/mergo/README.md
vendored
@@ -44,13 +44,21 @@ Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the
|
||||
|
||||
## Status
|
||||
|
||||
It is ready for production use. [It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, Microsoft, etc](https://github.com/imdario/mergo#mergo-in-the-wild).
|
||||
Mergo is stable and frozen, ready for production. Check a short list of the projects using at large scale it [here](https://github.com/imdario/mergo#mergo-in-the-wild).
|
||||
|
||||
No new features are accepted. They will be considered for a future v2 that improves the implementation and fixes bugs for corner cases.
|
||||
|
||||
### Important notes
|
||||
|
||||
#### 1.0.0
|
||||
|
||||
In [1.0.0](//github.com/imdario/mergo/releases/tag/1.0.0) Mergo moves to a vanity URL `dario.cat/mergo`.
|
||||
In [1.0.0](//github.com/imdario/mergo/releases/tag/1.0.0) Mergo moves to a vanity URL `dario.cat/mergo`. No more v1 versions will be released.
|
||||
|
||||
If the vanity URL is causing issues in your project due to a dependency pulling Mergo - it isn't a direct dependency in your project - it is recommended to use [replace](https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive) to pin the version to the last one with the old import URL:
|
||||
|
||||
```
|
||||
replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.16
|
||||
```
|
||||
|
||||
#### 0.3.9
|
||||
|
||||
@@ -64,55 +72,23 @@ If you were using Mergo before April 6th, 2015, please check your project works
|
||||
|
||||
If Mergo is useful to you, consider buying me a coffee, a beer, or making a monthly donation to allow me to keep building great free software. :heart_eyes:
|
||||
|
||||
<a href='https://ko-fi.com/B0B58839' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://az743702.vo.msecnd.net/cdn/kofi1.png?v=0' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
||||
<a href="https://liberapay.com/dario/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>
|
||||
<a href='https://github.com/sponsors/imdario' target='_blank'><img alt="Become my sponsor" src="https://img.shields.io/github/sponsors/imdario?style=for-the-badge" /></a>
|
||||
|
||||
### Mergo in the wild
|
||||
|
||||
- [moby/moby](https://github.com/moby/moby)
|
||||
- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
|
||||
- [vmware/dispatch](https://github.com/vmware/dispatch)
|
||||
- [Shopify/themekit](https://github.com/Shopify/themekit)
|
||||
- [imdario/zas](https://github.com/imdario/zas)
|
||||
- [matcornic/hermes](https://github.com/matcornic/hermes)
|
||||
- [OpenBazaar/openbazaar-go](https://github.com/OpenBazaar/openbazaar-go)
|
||||
- [kataras/iris](https://github.com/kataras/iris)
|
||||
- [michaelsauter/crane](https://github.com/michaelsauter/crane)
|
||||
- [go-task/task](https://github.com/go-task/task)
|
||||
- [sensu/uchiwa](https://github.com/sensu/uchiwa)
|
||||
- [ory/hydra](https://github.com/ory/hydra)
|
||||
- [sisatech/vcli](https://github.com/sisatech/vcli)
|
||||
- [dairycart/dairycart](https://github.com/dairycart/dairycart)
|
||||
- [projectcalico/felix](https://github.com/projectcalico/felix)
|
||||
- [resin-os/balena](https://github.com/resin-os/balena)
|
||||
- [go-kivik/kivik](https://github.com/go-kivik/kivik)
|
||||
- [Telefonica/govice](https://github.com/Telefonica/govice)
|
||||
- [supergiant/supergiant](supergiant/supergiant)
|
||||
- [SergeyTsalkov/brooce](https://github.com/SergeyTsalkov/brooce)
|
||||
- [soniah/dnsmadeeasy](https://github.com/soniah/dnsmadeeasy)
|
||||
- [ohsu-comp-bio/funnel](https://github.com/ohsu-comp-bio/funnel)
|
||||
- [EagerIO/Stout](https://github.com/EagerIO/Stout)
|
||||
- [lynndylanhurley/defsynth-api](https://github.com/lynndylanhurley/defsynth-api)
|
||||
- [russross/canvasassignments](https://github.com/russross/canvasassignments)
|
||||
- [rdegges/cryptly-api](https://github.com/rdegges/cryptly-api)
|
||||
- [casualjim/exeggutor](https://github.com/casualjim/exeggutor)
|
||||
- [divshot/gitling](https://github.com/divshot/gitling)
|
||||
- [RWJMurphy/gorl](https://github.com/RWJMurphy/gorl)
|
||||
- [andrerocker/deploy42](https://github.com/andrerocker/deploy42)
|
||||
- [elwinar/rambler](https://github.com/elwinar/rambler)
|
||||
- [tmaiaroto/gopartman](https://github.com/tmaiaroto/gopartman)
|
||||
- [jfbus/impressionist](https://github.com/jfbus/impressionist)
|
||||
- [Jmeyering/zealot](https://github.com/Jmeyering/zealot)
|
||||
- [godep-migrator/rigger-host](https://github.com/godep-migrator/rigger-host)
|
||||
- [Dronevery/MultiwaySwitch-Go](https://github.com/Dronevery/MultiwaySwitch-Go)
|
||||
- [thoas/picfit](https://github.com/thoas/picfit)
|
||||
- [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server)
|
||||
- [jnuthong/item_search](https://github.com/jnuthong/item_search)
|
||||
- [bukalapak/snowboard](https://github.com/bukalapak/snowboard)
|
||||
- [containerssh/containerssh](https://github.com/containerssh/containerssh)
|
||||
- [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
|
||||
- [tjpnz/structbot](https://github.com/tjpnz/structbot)
|
||||
Mergo is used by [thousands](https://deps.dev/go/dario.cat%2Fmergo/v1.0.0/dependents) [of](https://deps.dev/go/github.com%2Fimdario%2Fmergo/v0.3.16/dependents) [projects](https://deps.dev/go/github.com%2Fimdario%2Fmergo/v0.3.12), including:
|
||||
|
||||
* [containerd/containerd](https://github.com/containerd/containerd)
|
||||
* [datadog/datadog-agent](https://github.com/datadog/datadog-agent)
|
||||
* [docker/cli/](https://github.com/docker/cli/)
|
||||
* [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
|
||||
* [go-micro/go-micro](https://github.com/go-micro/go-micro)
|
||||
* [grafana/loki](https://github.com/grafana/loki)
|
||||
* [masterminds/sprig](github.com/Masterminds/sprig)
|
||||
* [moby/moby](https://github.com/moby/moby)
|
||||
* [slackhq/nebula](https://github.com/slackhq/nebula)
|
||||
* [volcano-sh/volcano](https://github.com/volcano-sh/volcano)
|
||||
|
||||
## Install
|
||||
|
||||
@@ -141,6 +117,39 @@ if err := mergo.Merge(&dst, src, mergo.WithOverride); err != nil {
|
||||
}
|
||||
```
|
||||
|
||||
If you need to override pointers, so the source pointer's value is assigned to the destination's pointer, you must use `WithoutDereference`:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"dario.cat/mergo"
|
||||
)
|
||||
|
||||
type Foo struct {
|
||||
A *string
|
||||
B int64
|
||||
}
|
||||
|
||||
func main() {
|
||||
first := "first"
|
||||
second := "second"
|
||||
src := Foo{
|
||||
A: &first,
|
||||
B: 2,
|
||||
}
|
||||
|
||||
dest := Foo{
|
||||
A: &second,
|
||||
B: 1,
|
||||
}
|
||||
|
||||
mergo.Merge(&dest, src, mergo.WithOverride, mergo.WithoutDereference)
|
||||
}
|
||||
```
|
||||
|
||||
Additionally, you can map a `map[string]interface{}` to a struct (and otherwise, from struct to map), following the same restrictions as in `Merge()`. Keys are capitalized to find each corresponding exported field.
|
||||
|
||||
```go
|
||||
@@ -181,10 +190,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
Note: if test are failing due missing package, please execute:
|
||||
|
||||
go get gopkg.in/yaml.v3
|
||||
|
||||
### Transformers
|
||||
|
||||
Transformers allow to merge specific types differently than in the default behavior. In other words, now you can customize how some types are merged. For example, `time.Time` is a struct; it doesn't have zero value but IsZero can return true because it has fields with zero value. How can we merge a non-zero `time.Time`?
|
||||
|
||||
4
vendor/dario.cat/mergo/SECURITY.md
vendored
4
vendor/dario.cat/mergo/SECURITY.md
vendored
@@ -4,8 +4,8 @@
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 0.3.x | :white_check_mark: |
|
||||
| < 0.3 | :x: |
|
||||
| 1.x.x | :white_check_mark: |
|
||||
| < 1.0 | :x: |
|
||||
|
||||
## Security contact information
|
||||
|
||||
|
||||
2
vendor/dario.cat/mergo/map.go
vendored
2
vendor/dario.cat/mergo/map.go
vendored
@@ -58,7 +58,7 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, conf
|
||||
}
|
||||
fieldName := field.Name
|
||||
fieldName = changeInitialCase(fieldName, unicode.ToLower)
|
||||
if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v), !config.ShouldNotDereference) || overwrite) {
|
||||
if _, ok := dstMap[fieldName]; !ok || (!isEmptyValue(reflect.ValueOf(src.Field(i).Interface()), !config.ShouldNotDereference) && overwrite) || config.overwriteWithEmptyValue {
|
||||
dstMap[fieldName] = src.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/dario.cat/mergo/merge.go
vendored
2
vendor/dario.cat/mergo/merge.go
vendored
@@ -269,7 +269,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
|
||||
if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
} else if src.Elem().Kind() != reflect.Struct {
|
||||
if overwriteWithEmptySrc || (overwrite && !src.IsNil()) || dst.IsNil() {
|
||||
dst.Set(src)
|
||||
}
|
||||
|
||||
10
vendor/github.com/Microsoft/go-winio/.golangci.yml
generated
vendored
10
vendor/github.com/Microsoft/go-winio/.golangci.yml
generated
vendored
@@ -1,7 +1,3 @@
|
||||
run:
|
||||
skip-dirs:
|
||||
- pkg/etw/sample
|
||||
|
||||
linters:
|
||||
enable:
|
||||
# style
|
||||
@@ -20,9 +16,13 @@ linters:
|
||||
- gofmt # files are gofmt'ed
|
||||
- gosec # security
|
||||
- nilerr # returns nil even with non-nil error
|
||||
- thelper # test helpers without t.Helper()
|
||||
- unparam # unused function params
|
||||
|
||||
issues:
|
||||
exclude-dirs:
|
||||
- pkg/etw/sample
|
||||
|
||||
exclude-rules:
|
||||
# err is very often shadowed in nested scopes
|
||||
- linters:
|
||||
@@ -69,9 +69,7 @@ linters-settings:
|
||||
# struct order is often for Win32 compat
|
||||
# also, ignore pointer bytes/GC issues for now until performance becomes an issue
|
||||
- fieldalignment
|
||||
check-shadowing: true
|
||||
nolintlint:
|
||||
allow-leading-space: false
|
||||
require-explanation: true
|
||||
require-specific: true
|
||||
revive:
|
||||
|
||||
33
vendor/github.com/Microsoft/go-winio/backup.go
generated
vendored
33
vendor/github.com/Microsoft/go-winio/backup.go
generated
vendored
@@ -10,14 +10,14 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
|
||||
"github.com/Microsoft/go-winio/internal/fs"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead
|
||||
//sys backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite
|
||||
//sys backupRead(h windows.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead
|
||||
//sys backupWrite(h windows.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite
|
||||
|
||||
const (
|
||||
BackupData = uint32(iota + 1)
|
||||
@@ -104,7 +104,7 @@ func (r *BackupStreamReader) Next() (*BackupHeader, error) {
|
||||
if err := binary.Read(r.r, binary.LittleEndian, name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hdr.Name = syscall.UTF16ToString(name)
|
||||
hdr.Name = windows.UTF16ToString(name)
|
||||
}
|
||||
if wsi.StreamID == BackupSparseBlock {
|
||||
if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil {
|
||||
@@ -205,7 +205,7 @@ func NewBackupFileReader(f *os.File, includeSecurity bool) *BackupFileReader {
|
||||
// Read reads a backup stream from the file by calling the Win32 API BackupRead().
|
||||
func (r *BackupFileReader) Read(b []byte) (int, error) {
|
||||
var bytesRead uint32
|
||||
err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx)
|
||||
err := backupRead(windows.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx)
|
||||
if err != nil {
|
||||
return 0, &os.PathError{Op: "BackupRead", Path: r.f.Name(), Err: err}
|
||||
}
|
||||
@@ -220,7 +220,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) {
|
||||
// the underlying file.
|
||||
func (r *BackupFileReader) Close() error {
|
||||
if r.ctx != 0 {
|
||||
_ = backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
|
||||
_ = backupRead(windows.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
|
||||
runtime.KeepAlive(r.f)
|
||||
r.ctx = 0
|
||||
}
|
||||
@@ -244,7 +244,7 @@ func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter {
|
||||
// Write restores a portion of the file using the provided backup stream.
|
||||
func (w *BackupFileWriter) Write(b []byte) (int, error) {
|
||||
var bytesWritten uint32
|
||||
err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx)
|
||||
err := backupWrite(windows.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx)
|
||||
if err != nil {
|
||||
return 0, &os.PathError{Op: "BackupWrite", Path: w.f.Name(), Err: err}
|
||||
}
|
||||
@@ -259,7 +259,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) {
|
||||
// close the underlying file.
|
||||
func (w *BackupFileWriter) Close() error {
|
||||
if w.ctx != 0 {
|
||||
_ = backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
|
||||
_ = backupWrite(windows.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
|
||||
runtime.KeepAlive(w.f)
|
||||
w.ctx = 0
|
||||
}
|
||||
@@ -271,17 +271,14 @@ func (w *BackupFileWriter) Close() error {
|
||||
//
|
||||
// If the file opened was a directory, it cannot be used with Readdir().
|
||||
func OpenForBackup(path string, access uint32, share uint32, createmode uint32) (*os.File, error) {
|
||||
winPath, err := syscall.UTF16FromString(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h, err := syscall.CreateFile(&winPath[0],
|
||||
access,
|
||||
share,
|
||||
h, err := fs.CreateFile(path,
|
||||
fs.AccessMask(access),
|
||||
fs.FileShareMode(share),
|
||||
nil,
|
||||
createmode,
|
||||
syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT,
|
||||
0)
|
||||
fs.FileCreationDisposition(createmode),
|
||||
fs.FILE_FLAG_BACKUP_SEMANTICS|fs.FILE_FLAG_OPEN_REPARSE_POINT,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
err = &os.PathError{Op: "open", Path: path, Err: err}
|
||||
return nil, err
|
||||
|
||||
85
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
85
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
@@ -15,26 +15,11 @@ import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx
|
||||
//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort
|
||||
//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus
|
||||
//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes
|
||||
//sys wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult
|
||||
|
||||
type atomicBool int32
|
||||
|
||||
func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
|
||||
func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) }
|
||||
func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) }
|
||||
|
||||
//revive:disable-next-line:predeclared Keep "new" to maintain consistency with "atomic" pkg
|
||||
func (b *atomicBool) swap(new bool) bool {
|
||||
var newInt int32
|
||||
if new {
|
||||
newInt = 1
|
||||
}
|
||||
return atomic.SwapInt32((*int32)(b), newInt) == 1
|
||||
}
|
||||
//sys cancelIoEx(file windows.Handle, o *windows.Overlapped) (err error) = CancelIoEx
|
||||
//sys createIoCompletionPort(file windows.Handle, port windows.Handle, key uintptr, threadCount uint32) (newport windows.Handle, err error) = CreateIoCompletionPort
|
||||
//sys getQueuedCompletionStatus(port windows.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus
|
||||
//sys setFileCompletionNotificationModes(h windows.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes
|
||||
//sys wsaGetOverlappedResult(h windows.Handle, o *windows.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult
|
||||
|
||||
var (
|
||||
ErrFileClosed = errors.New("file has already been closed")
|
||||
@@ -50,7 +35,7 @@ func (*timeoutError) Temporary() bool { return true }
|
||||
type timeoutChan chan struct{}
|
||||
|
||||
var ioInitOnce sync.Once
|
||||
var ioCompletionPort syscall.Handle
|
||||
var ioCompletionPort windows.Handle
|
||||
|
||||
// ioResult contains the result of an asynchronous IO operation.
|
||||
type ioResult struct {
|
||||
@@ -60,12 +45,12 @@ type ioResult struct {
|
||||
|
||||
// ioOperation represents an outstanding asynchronous Win32 IO.
|
||||
type ioOperation struct {
|
||||
o syscall.Overlapped
|
||||
o windows.Overlapped
|
||||
ch chan ioResult
|
||||
}
|
||||
|
||||
func initIO() {
|
||||
h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff)
|
||||
h, err := createIoCompletionPort(windows.InvalidHandle, 0, 0, 0xffffffff)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -76,10 +61,10 @@ func initIO() {
|
||||
// win32File implements Reader, Writer, and Closer on a Win32 handle without blocking in a syscall.
|
||||
// It takes ownership of this handle and will close it if it is garbage collected.
|
||||
type win32File struct {
|
||||
handle syscall.Handle
|
||||
handle windows.Handle
|
||||
wg sync.WaitGroup
|
||||
wgLock sync.RWMutex
|
||||
closing atomicBool
|
||||
closing atomic.Bool
|
||||
socket bool
|
||||
readDeadline deadlineHandler
|
||||
writeDeadline deadlineHandler
|
||||
@@ -90,11 +75,11 @@ type deadlineHandler struct {
|
||||
channel timeoutChan
|
||||
channelLock sync.RWMutex
|
||||
timer *time.Timer
|
||||
timedout atomicBool
|
||||
timedout atomic.Bool
|
||||
}
|
||||
|
||||
// makeWin32File makes a new win32File from an existing file handle.
|
||||
func makeWin32File(h syscall.Handle) (*win32File, error) {
|
||||
func makeWin32File(h windows.Handle) (*win32File, error) {
|
||||
f := &win32File{handle: h}
|
||||
ioInitOnce.Do(initIO)
|
||||
_, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff)
|
||||
@@ -110,7 +95,12 @@ func makeWin32File(h syscall.Handle) (*win32File, error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// Deprecated: use NewOpenFile instead.
|
||||
func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
|
||||
return NewOpenFile(windows.Handle(h))
|
||||
}
|
||||
|
||||
func NewOpenFile(h windows.Handle) (io.ReadWriteCloser, error) {
|
||||
// If we return the result of makeWin32File directly, it can result in an
|
||||
// interface-wrapped nil, rather than a nil interface value.
|
||||
f, err := makeWin32File(h)
|
||||
@@ -124,13 +114,13 @@ func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
|
||||
func (f *win32File) closeHandle() {
|
||||
f.wgLock.Lock()
|
||||
// Atomically set that we are closing, releasing the resources only once.
|
||||
if !f.closing.swap(true) {
|
||||
if !f.closing.Swap(true) {
|
||||
f.wgLock.Unlock()
|
||||
// cancel all IO and wait for it to complete
|
||||
_ = cancelIoEx(f.handle, nil)
|
||||
f.wg.Wait()
|
||||
// at this point, no new IO can start
|
||||
syscall.Close(f.handle)
|
||||
windows.Close(f.handle)
|
||||
f.handle = 0
|
||||
} else {
|
||||
f.wgLock.Unlock()
|
||||
@@ -145,14 +135,14 @@ func (f *win32File) Close() error {
|
||||
|
||||
// IsClosed checks if the file has been closed.
|
||||
func (f *win32File) IsClosed() bool {
|
||||
return f.closing.isSet()
|
||||
return f.closing.Load()
|
||||
}
|
||||
|
||||
// prepareIO prepares for a new IO operation.
|
||||
// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning.
|
||||
func (f *win32File) prepareIO() (*ioOperation, error) {
|
||||
f.wgLock.RLock()
|
||||
if f.closing.isSet() {
|
||||
if f.closing.Load() {
|
||||
f.wgLock.RUnlock()
|
||||
return nil, ErrFileClosed
|
||||
}
|
||||
@@ -164,12 +154,12 @@ func (f *win32File) prepareIO() (*ioOperation, error) {
|
||||
}
|
||||
|
||||
// ioCompletionProcessor processes completed async IOs forever.
|
||||
func ioCompletionProcessor(h syscall.Handle) {
|
||||
func ioCompletionProcessor(h windows.Handle) {
|
||||
for {
|
||||
var bytes uint32
|
||||
var key uintptr
|
||||
var op *ioOperation
|
||||
err := getQueuedCompletionStatus(h, &bytes, &key, &op, syscall.INFINITE)
|
||||
err := getQueuedCompletionStatus(h, &bytes, &key, &op, windows.INFINITE)
|
||||
if op == nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -182,11 +172,11 @@ func ioCompletionProcessor(h syscall.Handle) {
|
||||
// asyncIO processes the return value from ReadFile or WriteFile, blocking until
|
||||
// the operation has actually completed.
|
||||
func (f *win32File) asyncIO(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) {
|
||||
if err != syscall.ERROR_IO_PENDING { //nolint:errorlint // err is Errno
|
||||
if err != windows.ERROR_IO_PENDING { //nolint:errorlint // err is Errno
|
||||
return int(bytes), err
|
||||
}
|
||||
|
||||
if f.closing.isSet() {
|
||||
if f.closing.Load() {
|
||||
_ = cancelIoEx(f.handle, &c.o)
|
||||
}
|
||||
|
||||
@@ -201,8 +191,8 @@ func (f *win32File) asyncIO(c *ioOperation, d *deadlineHandler, bytes uint32, er
|
||||
select {
|
||||
case r = <-c.ch:
|
||||
err = r.err
|
||||
if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno
|
||||
if f.closing.isSet() {
|
||||
if err == windows.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno
|
||||
if f.closing.Load() {
|
||||
err = ErrFileClosed
|
||||
}
|
||||
} else if err != nil && f.socket {
|
||||
@@ -214,7 +204,7 @@ func (f *win32File) asyncIO(c *ioOperation, d *deadlineHandler, bytes uint32, er
|
||||
_ = cancelIoEx(f.handle, &c.o)
|
||||
r = <-c.ch
|
||||
err = r.err
|
||||
if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno
|
||||
if err == windows.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno
|
||||
err = ErrTimeout
|
||||
}
|
||||
}
|
||||
@@ -235,23 +225,22 @@ func (f *win32File) Read(b []byte) (int, error) {
|
||||
}
|
||||
defer f.wg.Done()
|
||||
|
||||
if f.readDeadline.timedout.isSet() {
|
||||
if f.readDeadline.timedout.Load() {
|
||||
return 0, ErrTimeout
|
||||
}
|
||||
|
||||
var bytes uint32
|
||||
err = syscall.ReadFile(f.handle, b, &bytes, &c.o)
|
||||
err = windows.ReadFile(f.handle, b, &bytes, &c.o)
|
||||
n, err := f.asyncIO(c, &f.readDeadline, bytes, err)
|
||||
runtime.KeepAlive(b)
|
||||
|
||||
// Handle EOF conditions.
|
||||
if err == nil && n == 0 && len(b) != 0 {
|
||||
return 0, io.EOF
|
||||
} else if err == syscall.ERROR_BROKEN_PIPE { //nolint:errorlint // err is Errno
|
||||
} else if err == windows.ERROR_BROKEN_PIPE { //nolint:errorlint // err is Errno
|
||||
return 0, io.EOF
|
||||
} else {
|
||||
return n, err
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Write writes to a file handle.
|
||||
@@ -262,12 +251,12 @@ func (f *win32File) Write(b []byte) (int, error) {
|
||||
}
|
||||
defer f.wg.Done()
|
||||
|
||||
if f.writeDeadline.timedout.isSet() {
|
||||
if f.writeDeadline.timedout.Load() {
|
||||
return 0, ErrTimeout
|
||||
}
|
||||
|
||||
var bytes uint32
|
||||
err = syscall.WriteFile(f.handle, b, &bytes, &c.o)
|
||||
err = windows.WriteFile(f.handle, b, &bytes, &c.o)
|
||||
n, err := f.asyncIO(c, &f.writeDeadline, bytes, err)
|
||||
runtime.KeepAlive(b)
|
||||
return n, err
|
||||
@@ -282,7 +271,7 @@ func (f *win32File) SetWriteDeadline(deadline time.Time) error {
|
||||
}
|
||||
|
||||
func (f *win32File) Flush() error {
|
||||
return syscall.FlushFileBuffers(f.handle)
|
||||
return windows.FlushFileBuffers(f.handle)
|
||||
}
|
||||
|
||||
func (f *win32File) Fd() uintptr {
|
||||
@@ -299,7 +288,7 @@ func (d *deadlineHandler) set(deadline time.Time) error {
|
||||
}
|
||||
d.timer = nil
|
||||
}
|
||||
d.timedout.setFalse()
|
||||
d.timedout.Store(false)
|
||||
|
||||
select {
|
||||
case <-d.channel:
|
||||
@@ -314,7 +303,7 @@ func (d *deadlineHandler) set(deadline time.Time) error {
|
||||
}
|
||||
|
||||
timeoutIO := func() {
|
||||
d.timedout.setTrue()
|
||||
d.timedout.Store(true)
|
||||
close(d.channel)
|
||||
}
|
||||
|
||||
|
||||
22
vendor/github.com/Microsoft/go-winio/fileinfo.go
generated
vendored
22
vendor/github.com/Microsoft/go-winio/fileinfo.go
generated
vendored
@@ -18,9 +18,18 @@ type FileBasicInfo struct {
|
||||
_ uint32 // padding
|
||||
}
|
||||
|
||||
// alignedFileBasicInfo is a FileBasicInfo, but aligned to uint64 by containing
|
||||
// uint64 rather than windows.Filetime. Filetime contains two uint32s. uint64
|
||||
// alignment is necessary to pass this as FILE_BASIC_INFO.
|
||||
type alignedFileBasicInfo struct {
|
||||
CreationTime, LastAccessTime, LastWriteTime, ChangeTime uint64
|
||||
FileAttributes uint32
|
||||
_ uint32 // padding
|
||||
}
|
||||
|
||||
// GetFileBasicInfo retrieves times and attributes for a file.
|
||||
func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
|
||||
bi := &FileBasicInfo{}
|
||||
bi := &alignedFileBasicInfo{}
|
||||
if err := windows.GetFileInformationByHandleEx(
|
||||
windows.Handle(f.Fd()),
|
||||
windows.FileBasicInfo,
|
||||
@@ -30,16 +39,21 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
|
||||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(f)
|
||||
return bi, nil
|
||||
// Reinterpret the alignedFileBasicInfo as a FileBasicInfo so it matches the
|
||||
// public API of this module. The data may be unnecessarily aligned.
|
||||
return (*FileBasicInfo)(unsafe.Pointer(bi)), nil
|
||||
}
|
||||
|
||||
// SetFileBasicInfo sets times and attributes for a file.
|
||||
func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
|
||||
// Create an alignedFileBasicInfo based on a FileBasicInfo. The copy is
|
||||
// suitable to pass to GetFileInformationByHandleEx.
|
||||
biAligned := *(*alignedFileBasicInfo)(unsafe.Pointer(bi))
|
||||
if err := windows.SetFileInformationByHandle(
|
||||
windows.Handle(f.Fd()),
|
||||
windows.FileBasicInfo,
|
||||
(*byte)(unsafe.Pointer(bi)),
|
||||
uint32(unsafe.Sizeof(*bi)),
|
||||
(*byte)(unsafe.Pointer(&biAligned)),
|
||||
uint32(unsafe.Sizeof(biAligned)),
|
||||
); err != nil {
|
||||
return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
|
||||
}
|
||||
|
||||
47
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
47
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
@@ -10,7 +10,6 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
@@ -181,13 +180,13 @@ type HvsockConn struct {
|
||||
var _ net.Conn = &HvsockConn{}
|
||||
|
||||
func newHVSocket() (*win32File, error) {
|
||||
fd, err := syscall.Socket(afHVSock, syscall.SOCK_STREAM, 1)
|
||||
fd, err := windows.Socket(afHVSock, windows.SOCK_STREAM, 1)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("socket", err)
|
||||
}
|
||||
f, err := makeWin32File(fd)
|
||||
if err != nil {
|
||||
syscall.Close(fd)
|
||||
windows.Close(fd)
|
||||
return nil, err
|
||||
}
|
||||
f.socket = true
|
||||
@@ -197,16 +196,24 @@ func newHVSocket() (*win32File, error) {
|
||||
// ListenHvsock listens for connections on the specified hvsock address.
|
||||
func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) {
|
||||
l := &HvsockListener{addr: *addr}
|
||||
sock, err := newHVSocket()
|
||||
|
||||
var sock *win32File
|
||||
sock, err = newHVSocket()
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", err)
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = sock.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
sa := addr.raw()
|
||||
err = socket.Bind(windows.Handle(sock.handle), &sa)
|
||||
err = socket.Bind(sock.handle, &sa)
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", os.NewSyscallError("socket", err))
|
||||
}
|
||||
err = syscall.Listen(sock.handle, 16)
|
||||
err = windows.Listen(sock.handle, 16)
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", os.NewSyscallError("listen", err))
|
||||
}
|
||||
@@ -246,7 +253,7 @@ func (l *HvsockListener) Accept() (_ net.Conn, err error) {
|
||||
var addrbuf [addrlen * 2]byte
|
||||
|
||||
var bytes uint32
|
||||
err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0 /* rxdatalen */, addrlen, addrlen, &bytes, &c.o)
|
||||
err = windows.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0 /* rxdatalen */, addrlen, addrlen, &bytes, &c.o)
|
||||
if _, err = l.sock.asyncIO(c, nil, bytes, err); err != nil {
|
||||
return nil, l.opErr("accept", os.NewSyscallError("acceptex", err))
|
||||
}
|
||||
@@ -263,7 +270,7 @@ func (l *HvsockListener) Accept() (_ net.Conn, err error) {
|
||||
conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen])))
|
||||
|
||||
// initialize the accepted socket and update its properties with those of the listening socket
|
||||
if err = windows.Setsockopt(windows.Handle(sock.handle),
|
||||
if err = windows.Setsockopt(sock.handle,
|
||||
windows.SOL_SOCKET, windows.SO_UPDATE_ACCEPT_CONTEXT,
|
||||
(*byte)(unsafe.Pointer(&l.sock.handle)), int32(unsafe.Sizeof(l.sock.handle))); err != nil {
|
||||
return nil, conn.opErr("accept", os.NewSyscallError("setsockopt", err))
|
||||
@@ -334,7 +341,7 @@ func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *Hvsock
|
||||
}()
|
||||
|
||||
sa := addr.raw()
|
||||
err = socket.Bind(windows.Handle(sock.handle), &sa)
|
||||
err = socket.Bind(sock.handle, &sa)
|
||||
if err != nil {
|
||||
return nil, conn.opErr(op, os.NewSyscallError("bind", err))
|
||||
}
|
||||
@@ -347,7 +354,7 @@ func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *Hvsock
|
||||
var bytes uint32
|
||||
for i := uint(0); i <= d.Retries; i++ {
|
||||
err = socket.ConnectEx(
|
||||
windows.Handle(sock.handle),
|
||||
sock.handle,
|
||||
&sa,
|
||||
nil, // sendBuf
|
||||
0, // sendDataLen
|
||||
@@ -367,7 +374,7 @@ func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *Hvsock
|
||||
|
||||
// update the connection properties, so shutdown can be used
|
||||
if err = windows.Setsockopt(
|
||||
windows.Handle(sock.handle),
|
||||
sock.handle,
|
||||
windows.SOL_SOCKET,
|
||||
windows.SO_UPDATE_CONNECT_CONTEXT,
|
||||
nil, // optvalue
|
||||
@@ -378,7 +385,7 @@ func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *Hvsock
|
||||
|
||||
// get the local name
|
||||
var sal rawHvsockAddr
|
||||
err = socket.GetSockName(windows.Handle(sock.handle), &sal)
|
||||
err = socket.GetSockName(sock.handle, &sal)
|
||||
if err != nil {
|
||||
return nil, conn.opErr(op, os.NewSyscallError("getsockname", err))
|
||||
}
|
||||
@@ -421,7 +428,7 @@ func (d *HvsockDialer) redialWait(ctx context.Context) (err error) {
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
// assumes error is a plain, unwrapped syscall.Errno provided by direct syscall.
|
||||
// assumes error is a plain, unwrapped windows.Errno provided by direct syscall.
|
||||
func canRedial(err error) bool {
|
||||
//nolint:errorlint // guaranteed to be an Errno
|
||||
switch err {
|
||||
@@ -447,9 +454,9 @@ func (conn *HvsockConn) Read(b []byte) (int, error) {
|
||||
return 0, conn.opErr("read", err)
|
||||
}
|
||||
defer conn.sock.wg.Done()
|
||||
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||
buf := windows.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||
var flags, bytes uint32
|
||||
err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil)
|
||||
err = windows.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil)
|
||||
n, err := conn.sock.asyncIO(c, &conn.sock.readDeadline, bytes, err)
|
||||
if err != nil {
|
||||
var eno windows.Errno
|
||||
@@ -482,9 +489,9 @@ func (conn *HvsockConn) write(b []byte) (int, error) {
|
||||
return 0, conn.opErr("write", err)
|
||||
}
|
||||
defer conn.sock.wg.Done()
|
||||
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||
buf := windows.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||
var bytes uint32
|
||||
err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil)
|
||||
err = windows.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil)
|
||||
n, err := conn.sock.asyncIO(c, &conn.sock.writeDeadline, bytes, err)
|
||||
if err != nil {
|
||||
var eno windows.Errno
|
||||
@@ -511,7 +518,7 @@ func (conn *HvsockConn) shutdown(how int) error {
|
||||
return socket.ErrSocketClosed
|
||||
}
|
||||
|
||||
err := syscall.Shutdown(conn.sock.handle, how)
|
||||
err := windows.Shutdown(conn.sock.handle, how)
|
||||
if err != nil {
|
||||
// If the connection was closed, shutdowns fail with "not connected"
|
||||
if errors.Is(err, windows.WSAENOTCONN) ||
|
||||
@@ -525,7 +532,7 @@ func (conn *HvsockConn) shutdown(how int) error {
|
||||
|
||||
// CloseRead shuts down the read end of the socket, preventing future read operations.
|
||||
func (conn *HvsockConn) CloseRead() error {
|
||||
err := conn.shutdown(syscall.SHUT_RD)
|
||||
err := conn.shutdown(windows.SHUT_RD)
|
||||
if err != nil {
|
||||
return conn.opErr("closeread", err)
|
||||
}
|
||||
@@ -535,7 +542,7 @@ func (conn *HvsockConn) CloseRead() error {
|
||||
// CloseWrite shuts down the write end of the socket, preventing future write operations and
|
||||
// notifying the other endpoint that no more data will be written.
|
||||
func (conn *HvsockConn) CloseWrite() error {
|
||||
err := conn.shutdown(syscall.SHUT_WR)
|
||||
err := conn.shutdown(windows.SHUT_WR)
|
||||
if err != nil {
|
||||
return conn.opErr("closewrite", err)
|
||||
}
|
||||
|
||||
72
vendor/github.com/Microsoft/go-winio/internal/fs/fs.go
generated
vendored
72
vendor/github.com/Microsoft/go-winio/internal/fs/fs.go
generated
vendored
@@ -11,12 +11,14 @@ import (
|
||||
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go fs.go
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
|
||||
//sys CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateFileW
|
||||
//sys CreateFile(name string, access AccessMask, mode FileShareMode, sa *windows.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateFileW
|
||||
|
||||
const NullHandle windows.Handle = 0
|
||||
|
||||
// AccessMask defines standard, specific, and generic rights.
|
||||
//
|
||||
// Used with CreateFile and NtCreateFile (and co.).
|
||||
//
|
||||
// Bitmask:
|
||||
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
@@ -47,6 +49,12 @@ const (
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew#parameters
|
||||
FILE_ANY_ACCESS AccessMask = 0
|
||||
|
||||
GENERIC_READ AccessMask = 0x8000_0000
|
||||
GENERIC_WRITE AccessMask = 0x4000_0000
|
||||
GENERIC_EXECUTE AccessMask = 0x2000_0000
|
||||
GENERIC_ALL AccessMask = 0x1000_0000
|
||||
ACCESS_SYSTEM_SECURITY AccessMask = 0x0100_0000
|
||||
|
||||
// Specific Object Access
|
||||
// from ntioapi.h
|
||||
|
||||
@@ -124,14 +132,32 @@ const (
|
||||
TRUNCATE_EXISTING FileCreationDisposition = 0x05
|
||||
)
|
||||
|
||||
// Create disposition values for NtCreate*
|
||||
type NTFileCreationDisposition uint32
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const (
|
||||
// From ntioapi.h
|
||||
|
||||
FILE_SUPERSEDE NTFileCreationDisposition = 0x00
|
||||
FILE_OPEN NTFileCreationDisposition = 0x01
|
||||
FILE_CREATE NTFileCreationDisposition = 0x02
|
||||
FILE_OPEN_IF NTFileCreationDisposition = 0x03
|
||||
FILE_OVERWRITE NTFileCreationDisposition = 0x04
|
||||
FILE_OVERWRITE_IF NTFileCreationDisposition = 0x05
|
||||
FILE_MAXIMUM_DISPOSITION NTFileCreationDisposition = 0x05
|
||||
)
|
||||
|
||||
// CreateFile and co. take flags or attributes together as one parameter.
|
||||
// Define alias until we can use generics to allow both
|
||||
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
|
||||
type FileFlagOrAttribute uint32
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const ( // from winnt.h
|
||||
const (
|
||||
// from winnt.h
|
||||
|
||||
FILE_FLAG_WRITE_THROUGH FileFlagOrAttribute = 0x8000_0000
|
||||
FILE_FLAG_OVERLAPPED FileFlagOrAttribute = 0x4000_0000
|
||||
FILE_FLAG_NO_BUFFERING FileFlagOrAttribute = 0x2000_0000
|
||||
@@ -145,17 +171,51 @@ const ( // from winnt.h
|
||||
FILE_FLAG_FIRST_PIPE_INSTANCE FileFlagOrAttribute = 0x0008_0000
|
||||
)
|
||||
|
||||
// NtCreate* functions take a dedicated CreateOptions parameter.
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/Winternl/nf-winternl-ntcreatefile
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/devnotes/nt-create-named-pipe-file
|
||||
type NTCreateOptions uint32
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const (
|
||||
// From ntioapi.h
|
||||
|
||||
FILE_DIRECTORY_FILE NTCreateOptions = 0x0000_0001
|
||||
FILE_WRITE_THROUGH NTCreateOptions = 0x0000_0002
|
||||
FILE_SEQUENTIAL_ONLY NTCreateOptions = 0x0000_0004
|
||||
FILE_NO_INTERMEDIATE_BUFFERING NTCreateOptions = 0x0000_0008
|
||||
|
||||
FILE_SYNCHRONOUS_IO_ALERT NTCreateOptions = 0x0000_0010
|
||||
FILE_SYNCHRONOUS_IO_NONALERT NTCreateOptions = 0x0000_0020
|
||||
FILE_NON_DIRECTORY_FILE NTCreateOptions = 0x0000_0040
|
||||
FILE_CREATE_TREE_CONNECTION NTCreateOptions = 0x0000_0080
|
||||
|
||||
FILE_COMPLETE_IF_OPLOCKED NTCreateOptions = 0x0000_0100
|
||||
FILE_NO_EA_KNOWLEDGE NTCreateOptions = 0x0000_0200
|
||||
FILE_DISABLE_TUNNELING NTCreateOptions = 0x0000_0400
|
||||
FILE_RANDOM_ACCESS NTCreateOptions = 0x0000_0800
|
||||
|
||||
FILE_DELETE_ON_CLOSE NTCreateOptions = 0x0000_1000
|
||||
FILE_OPEN_BY_FILE_ID NTCreateOptions = 0x0000_2000
|
||||
FILE_OPEN_FOR_BACKUP_INTENT NTCreateOptions = 0x0000_4000
|
||||
FILE_NO_COMPRESSION NTCreateOptions = 0x0000_8000
|
||||
)
|
||||
|
||||
type FileSQSFlag = FileFlagOrAttribute
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const ( // from winbase.h
|
||||
const (
|
||||
// from winbase.h
|
||||
|
||||
SECURITY_ANONYMOUS FileSQSFlag = FileSQSFlag(SecurityAnonymous << 16)
|
||||
SECURITY_IDENTIFICATION FileSQSFlag = FileSQSFlag(SecurityIdentification << 16)
|
||||
SECURITY_IMPERSONATION FileSQSFlag = FileSQSFlag(SecurityImpersonation << 16)
|
||||
SECURITY_DELEGATION FileSQSFlag = FileSQSFlag(SecurityDelegation << 16)
|
||||
|
||||
SECURITY_SQOS_PRESENT FileSQSFlag = 0x00100000
|
||||
SECURITY_VALID_SQOS_FLAGS FileSQSFlag = 0x001F0000
|
||||
SECURITY_SQOS_PRESENT FileSQSFlag = 0x0010_0000
|
||||
SECURITY_VALID_SQOS_FLAGS FileSQSFlag = 0x001F_0000
|
||||
)
|
||||
|
||||
// GetFinalPathNameByHandle flags
|
||||
|
||||
9
vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go
generated
vendored
9
vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go
generated
vendored
@@ -33,9 +33,6 @@ func errnoErr(e syscall.Errno) error {
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
// TODO: add more here, after collecting data on the common
|
||||
// error values see on Windows. (perhaps when running
|
||||
// all.bat?)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -45,7 +42,7 @@ var (
|
||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||
)
|
||||
|
||||
func CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) {
|
||||
func CreateFile(name string, access AccessMask, mode FileShareMode, sa *windows.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
@@ -54,8 +51,8 @@ func CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.
|
||||
return _CreateFile(_p0, access, mode, sa, createmode, attrs, templatefile)
|
||||
}
|
||||
|
||||
func _CreateFile(name *uint16, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
|
||||
func _CreateFile(name *uint16, access AccessMask, mode FileShareMode, sa *windows.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) {
|
||||
r0, _, e1 := syscall.SyscallN(procCreateFileW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile))
|
||||
handle = windows.Handle(r0)
|
||||
if handle == windows.InvalidHandle {
|
||||
err = errnoErr(e1)
|
||||
|
||||
8
vendor/github.com/Microsoft/go-winio/internal/socket/socket.go
generated
vendored
8
vendor/github.com/Microsoft/go-winio/internal/socket/socket.go
generated
vendored
@@ -156,9 +156,7 @@ func connectEx(
|
||||
bytesSent *uint32,
|
||||
overlapped *windows.Overlapped,
|
||||
) (err error) {
|
||||
// todo: after upgrading to 1.18, switch from syscall.Syscall9 to syscall.SyscallN
|
||||
r1, _, e1 := syscall.Syscall9(connectExFunc.addr,
|
||||
7,
|
||||
r1, _, e1 := syscall.SyscallN(connectExFunc.addr,
|
||||
uintptr(s),
|
||||
uintptr(name),
|
||||
uintptr(namelen),
|
||||
@@ -166,8 +164,8 @@ func connectEx(
|
||||
uintptr(sendDataLen),
|
||||
uintptr(unsafe.Pointer(bytesSent)),
|
||||
uintptr(unsafe.Pointer(overlapped)),
|
||||
0,
|
||||
0)
|
||||
)
|
||||
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
|
||||
9
vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go
generated
vendored
9
vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go
generated
vendored
@@ -33,9 +33,6 @@ func errnoErr(e syscall.Errno) error {
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
// TODO: add more here, after collecting data on the common
|
||||
// error values see on Windows. (perhaps when running
|
||||
// all.bat?)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -48,7 +45,7 @@ var (
|
||||
)
|
||||
|
||||
func bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
|
||||
r1, _, e1 := syscall.SyscallN(procbind.Addr(), uintptr(s), uintptr(name), uintptr(namelen))
|
||||
if r1 == socketError {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
@@ -56,7 +53,7 @@ func bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) {
|
||||
}
|
||||
|
||||
func getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen)))
|
||||
r1, _, e1 := syscall.SyscallN(procgetpeername.Addr(), uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen)))
|
||||
if r1 == socketError {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
@@ -64,7 +61,7 @@ func getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err err
|
||||
}
|
||||
|
||||
func getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen)))
|
||||
r1, _, e1 := syscall.SyscallN(procgetsockname.Addr(), uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen)))
|
||||
if r1 == socketError {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
|
||||
2
vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go
generated
vendored
@@ -62,7 +62,7 @@ func (b *WString) Free() {
|
||||
// ResizeTo grows the buffer to at least c and returns the new capacity, freeing the
|
||||
// previous buffer back into pool.
|
||||
func (b *WString) ResizeTo(c uint32) uint32 {
|
||||
// allready sufficient (or n is 0)
|
||||
// already sufficient (or n is 0)
|
||||
if c <= b.Cap() {
|
||||
return b.Cap()
|
||||
}
|
||||
|
||||
125
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
125
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
@@ -11,7 +11,6 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
@@ -20,20 +19,44 @@ import (
|
||||
"github.com/Microsoft/go-winio/internal/fs"
|
||||
)
|
||||
|
||||
//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
|
||||
//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW
|
||||
//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
|
||||
//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
|
||||
//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc
|
||||
//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) = ntdll.NtCreateNamedPipeFile
|
||||
//sys connectNamedPipe(pipe windows.Handle, o *windows.Overlapped) (err error) = ConnectNamedPipe
|
||||
//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *windows.SecurityAttributes) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateNamedPipeW
|
||||
//sys disconnectNamedPipe(pipe windows.Handle) (err error) = DisconnectNamedPipe
|
||||
//sys getNamedPipeInfo(pipe windows.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
|
||||
//sys getNamedPipeHandleState(pipe windows.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
|
||||
//sys ntCreateNamedPipeFile(pipe *windows.Handle, access ntAccessMask, oa *objectAttributes, iosb *ioStatusBlock, share ntFileShareMode, disposition ntFileCreationDisposition, options ntFileOptions, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) = ntdll.NtCreateNamedPipeFile
|
||||
//sys rtlNtStatusToDosError(status ntStatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
|
||||
//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) = ntdll.RtlDosPathNameToNtPathName_U
|
||||
//sys rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) = ntdll.RtlDefaultNpAcl
|
||||
|
||||
type PipeConn interface {
|
||||
net.Conn
|
||||
Disconnect() error
|
||||
Flush() error
|
||||
}
|
||||
|
||||
// type aliases for mkwinsyscall code
|
||||
type (
|
||||
ntAccessMask = fs.AccessMask
|
||||
ntFileShareMode = fs.FileShareMode
|
||||
ntFileCreationDisposition = fs.NTFileCreationDisposition
|
||||
ntFileOptions = fs.NTCreateOptions
|
||||
)
|
||||
|
||||
type ioStatusBlock struct {
|
||||
Status, Information uintptr
|
||||
}
|
||||
|
||||
// typedef struct _OBJECT_ATTRIBUTES {
|
||||
// ULONG Length;
|
||||
// HANDLE RootDirectory;
|
||||
// PUNICODE_STRING ObjectName;
|
||||
// ULONG Attributes;
|
||||
// PVOID SecurityDescriptor;
|
||||
// PVOID SecurityQualityOfService;
|
||||
// } OBJECT_ATTRIBUTES;
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_object_attributes
|
||||
type objectAttributes struct {
|
||||
Length uintptr
|
||||
RootDirectory uintptr
|
||||
@@ -49,6 +72,17 @@ type unicodeString struct {
|
||||
Buffer uintptr
|
||||
}
|
||||
|
||||
// typedef struct _SECURITY_DESCRIPTOR {
|
||||
// BYTE Revision;
|
||||
// BYTE Sbz1;
|
||||
// SECURITY_DESCRIPTOR_CONTROL Control;
|
||||
// PSID Owner;
|
||||
// PSID Group;
|
||||
// PACL Sacl;
|
||||
// PACL Dacl;
|
||||
// } SECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR;
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-security_descriptor
|
||||
type securityDescriptor struct {
|
||||
Revision byte
|
||||
Sbz1 byte
|
||||
@@ -80,6 +114,8 @@ type win32Pipe struct {
|
||||
path string
|
||||
}
|
||||
|
||||
var _ PipeConn = (*win32Pipe)(nil)
|
||||
|
||||
type win32MessageBytePipe struct {
|
||||
win32Pipe
|
||||
writeClosed bool
|
||||
@@ -103,6 +139,10 @@ func (f *win32Pipe) SetDeadline(t time.Time) error {
|
||||
return f.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
func (f *win32Pipe) Disconnect() error {
|
||||
return disconnectNamedPipe(f.win32File.handle)
|
||||
}
|
||||
|
||||
// CloseWrite closes the write side of a message pipe in byte mode.
|
||||
func (f *win32MessageBytePipe) CloseWrite() error {
|
||||
if f.writeClosed {
|
||||
@@ -146,7 +186,7 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
|
||||
// zero-byte message, ensure that all future Read() calls
|
||||
// also return EOF.
|
||||
f.readEOF = true
|
||||
} else if err == syscall.ERROR_MORE_DATA { //nolint:errorlint // err is Errno
|
||||
} else if err == windows.ERROR_MORE_DATA { //nolint:errorlint // err is Errno
|
||||
// ERROR_MORE_DATA indicates that the pipe's read mode is message mode
|
||||
// and the message still has more bytes. Treat this as a success, since
|
||||
// this package presents all named pipes as byte streams.
|
||||
@@ -164,21 +204,20 @@ func (s pipeAddress) String() string {
|
||||
}
|
||||
|
||||
// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
|
||||
func tryDialPipe(ctx context.Context, path *string, access fs.AccessMask) (syscall.Handle, error) {
|
||||
func tryDialPipe(ctx context.Context, path *string, access fs.AccessMask, impLevel PipeImpLevel) (windows.Handle, error) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return syscall.Handle(0), ctx.Err()
|
||||
return windows.Handle(0), ctx.Err()
|
||||
default:
|
||||
wh, err := fs.CreateFile(*path,
|
||||
h, err := fs.CreateFile(*path,
|
||||
access,
|
||||
0, // mode
|
||||
nil, // security attributes
|
||||
fs.OPEN_EXISTING,
|
||||
fs.FILE_FLAG_OVERLAPPED|fs.SECURITY_SQOS_PRESENT|fs.SECURITY_ANONYMOUS,
|
||||
fs.FILE_FLAG_OVERLAPPED|fs.SECURITY_SQOS_PRESENT|fs.FileSQSFlag(impLevel),
|
||||
0, // template file handle
|
||||
)
|
||||
h := syscall.Handle(wh)
|
||||
if err == nil {
|
||||
return h, nil
|
||||
}
|
||||
@@ -214,15 +253,33 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
|
||||
// DialPipeContext attempts to connect to a named pipe by `path` until `ctx`
|
||||
// cancellation or timeout.
|
||||
func DialPipeContext(ctx context.Context, path string) (net.Conn, error) {
|
||||
return DialPipeAccess(ctx, path, syscall.GENERIC_READ|syscall.GENERIC_WRITE)
|
||||
return DialPipeAccess(ctx, path, uint32(fs.GENERIC_READ|fs.GENERIC_WRITE))
|
||||
}
|
||||
|
||||
// PipeImpLevel is an enumeration of impersonation levels that may be set
|
||||
// when calling DialPipeAccessImpersonation.
|
||||
type PipeImpLevel uint32
|
||||
|
||||
const (
|
||||
PipeImpLevelAnonymous = PipeImpLevel(fs.SECURITY_ANONYMOUS)
|
||||
PipeImpLevelIdentification = PipeImpLevel(fs.SECURITY_IDENTIFICATION)
|
||||
PipeImpLevelImpersonation = PipeImpLevel(fs.SECURITY_IMPERSONATION)
|
||||
PipeImpLevelDelegation = PipeImpLevel(fs.SECURITY_DELEGATION)
|
||||
)
|
||||
|
||||
// DialPipeAccess attempts to connect to a named pipe by `path` with `access` until `ctx`
|
||||
// cancellation or timeout.
|
||||
func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, error) {
|
||||
return DialPipeAccessImpLevel(ctx, path, access, PipeImpLevelAnonymous)
|
||||
}
|
||||
|
||||
// DialPipeAccessImpLevel attempts to connect to a named pipe by `path` with
|
||||
// `access` at `impLevel` until `ctx` cancellation or timeout. The other
|
||||
// DialPipe* implementations use PipeImpLevelAnonymous.
|
||||
func DialPipeAccessImpLevel(ctx context.Context, path string, access uint32, impLevel PipeImpLevel) (net.Conn, error) {
|
||||
var err error
|
||||
var h syscall.Handle
|
||||
h, err = tryDialPipe(ctx, &path, fs.AccessMask(access))
|
||||
var h windows.Handle
|
||||
h, err = tryDialPipe(ctx, &path, fs.AccessMask(access), impLevel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -235,7 +292,7 @@ func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn,
|
||||
|
||||
f, err := makeWin32File(h)
|
||||
if err != nil {
|
||||
syscall.Close(h)
|
||||
windows.Close(h)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -255,7 +312,7 @@ type acceptResponse struct {
|
||||
}
|
||||
|
||||
type win32PipeListener struct {
|
||||
firstHandle syscall.Handle
|
||||
firstHandle windows.Handle
|
||||
path string
|
||||
config PipeConfig
|
||||
acceptCh chan (chan acceptResponse)
|
||||
@@ -263,8 +320,8 @@ type win32PipeListener struct {
|
||||
doneCh chan int
|
||||
}
|
||||
|
||||
func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (syscall.Handle, error) {
|
||||
path16, err := syscall.UTF16FromString(path)
|
||||
func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (windows.Handle, error) {
|
||||
path16, err := windows.UTF16FromString(path)
|
||||
if err != nil {
|
||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
}
|
||||
@@ -280,16 +337,20 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
|
||||
).Err(); err != nil {
|
||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
}
|
||||
defer localFree(ntPath.Buffer)
|
||||
defer windows.LocalFree(windows.Handle(ntPath.Buffer)) //nolint:errcheck
|
||||
oa.ObjectName = &ntPath
|
||||
oa.Attributes = windows.OBJ_CASE_INSENSITIVE
|
||||
|
||||
// The security descriptor is only needed for the first pipe.
|
||||
if first {
|
||||
if sd != nil {
|
||||
//todo: does `sdb` need to be allocated on the heap, or can go allocate it?
|
||||
l := uint32(len(sd))
|
||||
sdb := localAlloc(0, l)
|
||||
defer localFree(sdb)
|
||||
sdb, err := windows.LocalAlloc(0, l)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("LocalAlloc for security descriptor with of length %d: %w", l, err)
|
||||
}
|
||||
defer windows.LocalFree(windows.Handle(sdb)) //nolint:errcheck
|
||||
copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd)
|
||||
oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb))
|
||||
} else {
|
||||
@@ -298,7 +359,7 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
|
||||
if err := rtlDefaultNpAcl(&dacl).Err(); err != nil {
|
||||
return 0, fmt.Errorf("getting default named pipe ACL: %w", err)
|
||||
}
|
||||
defer localFree(dacl)
|
||||
defer windows.LocalFree(windows.Handle(dacl)) //nolint:errcheck
|
||||
|
||||
sdb := &securityDescriptor{
|
||||
Revision: 1,
|
||||
@@ -314,27 +375,27 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
|
||||
typ |= windows.FILE_PIPE_MESSAGE_TYPE
|
||||
}
|
||||
|
||||
disposition := uint32(windows.FILE_OPEN)
|
||||
access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE)
|
||||
disposition := fs.FILE_OPEN
|
||||
access := fs.GENERIC_READ | fs.GENERIC_WRITE | fs.SYNCHRONIZE
|
||||
if first {
|
||||
disposition = windows.FILE_CREATE
|
||||
disposition = fs.FILE_CREATE
|
||||
// By not asking for read or write access, the named pipe file system
|
||||
// will put this pipe into an initially disconnected state, blocking
|
||||
// client connections until the next call with first == false.
|
||||
access = syscall.SYNCHRONIZE
|
||||
access = fs.SYNCHRONIZE
|
||||
}
|
||||
|
||||
timeout := int64(-50 * 10000) // 50ms
|
||||
|
||||
var (
|
||||
h syscall.Handle
|
||||
h windows.Handle
|
||||
iosb ioStatusBlock
|
||||
)
|
||||
err = ntCreateNamedPipeFile(&h,
|
||||
access,
|
||||
&oa,
|
||||
&iosb,
|
||||
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE,
|
||||
fs.FILE_SHARE_READ|fs.FILE_SHARE_WRITE,
|
||||
disposition,
|
||||
0,
|
||||
typ,
|
||||
@@ -359,7 +420,7 @@ func (l *win32PipeListener) makeServerPipe() (*win32File, error) {
|
||||
}
|
||||
f, err := makeWin32File(h)
|
||||
if err != nil {
|
||||
syscall.Close(h)
|
||||
windows.Close(h)
|
||||
return nil, err
|
||||
}
|
||||
return f, nil
|
||||
@@ -418,7 +479,7 @@ func (l *win32PipeListener) listenerRoutine() {
|
||||
closed = err == ErrPipeListenerClosed //nolint:errorlint // err is Errno
|
||||
}
|
||||
}
|
||||
syscall.Close(l.firstHandle)
|
||||
windows.Close(l.firstHandle)
|
||||
l.firstHandle = 0
|
||||
// Notify Close() and Accept() callers that the handle has been closed.
|
||||
close(l.doneCh)
|
||||
|
||||
9
vendor/github.com/Microsoft/go-winio/privilege.go
generated
vendored
9
vendor/github.com/Microsoft/go-winio/privilege.go
generated
vendored
@@ -9,7 +9,6 @@ import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
@@ -18,8 +17,8 @@ import (
|
||||
//sys adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges
|
||||
//sys impersonateSelf(level uint32) (err error) = advapi32.ImpersonateSelf
|
||||
//sys revertToSelf() (err error) = advapi32.RevertToSelf
|
||||
//sys openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) = advapi32.OpenThreadToken
|
||||
//sys getCurrentThread() (h syscall.Handle) = GetCurrentThread
|
||||
//sys openThreadToken(thread windows.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) = advapi32.OpenThreadToken
|
||||
//sys getCurrentThread() (h windows.Handle) = GetCurrentThread
|
||||
//sys lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) = advapi32.LookupPrivilegeValueW
|
||||
//sys lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW
|
||||
//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW
|
||||
@@ -29,7 +28,7 @@ const (
|
||||
SE_PRIVILEGE_ENABLED = windows.SE_PRIVILEGE_ENABLED
|
||||
|
||||
//revive:disable-next-line:var-naming ALL_CAPS
|
||||
ERROR_NOT_ALL_ASSIGNED syscall.Errno = windows.ERROR_NOT_ALL_ASSIGNED
|
||||
ERROR_NOT_ALL_ASSIGNED windows.Errno = windows.ERROR_NOT_ALL_ASSIGNED
|
||||
|
||||
SeBackupPrivilege = "SeBackupPrivilege"
|
||||
SeRestorePrivilege = "SeRestorePrivilege"
|
||||
@@ -177,7 +176,7 @@ func newThreadToken() (windows.Token, error) {
|
||||
}
|
||||
|
||||
var token windows.Token
|
||||
err = openThreadToken(getCurrentThread(), syscall.TOKEN_ADJUST_PRIVILEGES|syscall.TOKEN_QUERY, false, &token)
|
||||
err = openThreadToken(getCurrentThread(), windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, false, &token)
|
||||
if err != nil {
|
||||
rerr := revertToSelf()
|
||||
if rerr != nil {
|
||||
|
||||
37
vendor/github.com/Microsoft/go-winio/sd.go
generated
vendored
37
vendor/github.com/Microsoft/go-winio/sd.go
generated
vendored
@@ -5,7 +5,7 @@ package winio
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
@@ -15,10 +15,6 @@ import (
|
||||
//sys lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountSidW
|
||||
//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW
|
||||
//sys convertStringSidToSid(str *uint16, sid **byte) (err error) = advapi32.ConvertStringSidToSidW
|
||||
//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
|
||||
//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
|
||||
//sys localFree(mem uintptr) = LocalFree
|
||||
//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength
|
||||
|
||||
type AccountLookupError struct {
|
||||
Name string
|
||||
@@ -64,7 +60,7 @@ func LookupSidByName(name string) (sid string, err error) {
|
||||
|
||||
var sidSize, sidNameUse, refDomainSize uint32
|
||||
err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse)
|
||||
if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno
|
||||
if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno
|
||||
return "", &AccountLookupError{name, err}
|
||||
}
|
||||
sidBuffer := make([]byte, sidSize)
|
||||
@@ -78,8 +74,8 @@ func LookupSidByName(name string) (sid string, err error) {
|
||||
if err != nil {
|
||||
return "", &AccountLookupError{name, err}
|
||||
}
|
||||
sid = syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:])
|
||||
localFree(uintptr(unsafe.Pointer(strBuffer)))
|
||||
sid = windows.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:])
|
||||
_, _ = windows.LocalFree(windows.Handle(unsafe.Pointer(strBuffer)))
|
||||
return sid, nil
|
||||
}
|
||||
|
||||
@@ -100,7 +96,7 @@ func LookupNameBySid(sid string) (name string, err error) {
|
||||
if err = convertStringSidToSid(sidBuffer, &sidPtr); err != nil {
|
||||
return "", &AccountLookupError{sid, err}
|
||||
}
|
||||
defer localFree(uintptr(unsafe.Pointer(sidPtr)))
|
||||
defer windows.LocalFree(windows.Handle(unsafe.Pointer(sidPtr))) //nolint:errcheck
|
||||
|
||||
var nameSize, refDomainSize, sidNameUse uint32
|
||||
err = lookupAccountSid(nil, sidPtr, nil, &nameSize, nil, &refDomainSize, &sidNameUse)
|
||||
@@ -120,25 +116,18 @@ func LookupNameBySid(sid string) (name string, err error) {
|
||||
}
|
||||
|
||||
func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
|
||||
var sdBuffer uintptr
|
||||
err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil)
|
||||
sd, err := windows.SecurityDescriptorFromString(sddl)
|
||||
if err != nil {
|
||||
return nil, &SddlConversionError{sddl, err}
|
||||
return nil, &SddlConversionError{Sddl: sddl, Err: err}
|
||||
}
|
||||
defer localFree(sdBuffer)
|
||||
sd := make([]byte, getSecurityDescriptorLength(sdBuffer))
|
||||
copy(sd, (*[0xffff]byte)(unsafe.Pointer(sdBuffer))[:len(sd)])
|
||||
return sd, nil
|
||||
b := unsafe.Slice((*byte)(unsafe.Pointer(sd)), sd.Length())
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func SecurityDescriptorToSddl(sd []byte) (string, error) {
|
||||
var sddl *uint16
|
||||
// The returned string length seems to include an arbitrary number of terminating NULs.
|
||||
// Don't use it.
|
||||
err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
if l := int(unsafe.Sizeof(windows.SECURITY_DESCRIPTOR{})); len(sd) < l {
|
||||
return "", fmt.Errorf("SecurityDescriptor (%d) smaller than expected (%d): %w", len(sd), l, windows.ERROR_INCORRECT_SIZE)
|
||||
}
|
||||
defer localFree(uintptr(unsafe.Pointer(sddl)))
|
||||
return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(sddl))[:]), nil
|
||||
s := (*windows.SECURITY_DESCRIPTOR)(unsafe.Pointer(&sd[0]))
|
||||
return s.String(), nil
|
||||
}
|
||||
|
||||
5
vendor/github.com/Microsoft/go-winio/tools.go
generated
vendored
5
vendor/github.com/Microsoft/go-winio/tools.go
generated
vendored
@@ -1,5 +0,0 @@
|
||||
//go:build tools
|
||||
|
||||
package winio
|
||||
|
||||
import _ "golang.org/x/tools/cmd/stringer"
|
||||
157
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
157
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
@@ -33,9 +33,6 @@ func errnoErr(e syscall.Errno) error {
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
// TODO: add more here, after collecting data on the common
|
||||
// error values see on Windows. (perhaps when running
|
||||
// all.bat?)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -46,11 +43,8 @@ var (
|
||||
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll")
|
||||
|
||||
procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
|
||||
procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW")
|
||||
procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW")
|
||||
procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
|
||||
procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW")
|
||||
procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength")
|
||||
procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
|
||||
procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
|
||||
procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW")
|
||||
@@ -65,12 +59,11 @@ var (
|
||||
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
|
||||
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
||||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
||||
procDisconnectNamedPipe = modkernel32.NewProc("DisconnectNamedPipe")
|
||||
procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
|
||||
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
|
||||
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo")
|
||||
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
|
||||
procLocalAlloc = modkernel32.NewProc("LocalAlloc")
|
||||
procLocalFree = modkernel32.NewProc("LocalFree")
|
||||
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
|
||||
procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile")
|
||||
procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl")
|
||||
@@ -84,7 +77,7 @@ func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, ou
|
||||
if releaseAll {
|
||||
_p0 = 1
|
||||
}
|
||||
r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize)))
|
||||
r0, _, e1 := syscall.SyscallN(procAdjustTokenPrivileges.Addr(), uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize)))
|
||||
success = r0 != 0
|
||||
if true {
|
||||
err = errnoErr(e1)
|
||||
@@ -92,33 +85,8 @@ func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, ou
|
||||
return
|
||||
}
|
||||
|
||||
func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func convertSidToStringSid(sid *byte, str **uint16) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(str)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size)
|
||||
}
|
||||
|
||||
func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0)
|
||||
r1, _, e1 := syscall.SyscallN(procConvertSidToStringSidW.Addr(), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
@@ -126,21 +94,15 @@ func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision
|
||||
}
|
||||
|
||||
func convertStringSidToSid(str *uint16, sid **byte) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(sid)), 0)
|
||||
r1, _, e1 := syscall.SyscallN(procConvertStringSidToSidW.Addr(), uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(sid)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getSecurityDescriptorLength(sd uintptr) (len uint32) {
|
||||
r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0)
|
||||
len = uint32(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func impersonateSelf(level uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0)
|
||||
r1, _, e1 := syscall.SyscallN(procImpersonateSelf.Addr(), uintptr(level))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
@@ -157,7 +119,7 @@ func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSiz
|
||||
}
|
||||
|
||||
func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
|
||||
r1, _, e1 := syscall.SyscallN(procLookupAccountNameW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
@@ -165,7 +127,7 @@ func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidS
|
||||
}
|
||||
|
||||
func lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
|
||||
r1, _, e1 := syscall.SyscallN(procLookupAccountSidW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
@@ -182,7 +144,7 @@ func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16,
|
||||
}
|
||||
|
||||
func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0)
|
||||
r1, _, e1 := syscall.SyscallN(procLookupPrivilegeDisplayNameW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
@@ -199,7 +161,7 @@ func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *
|
||||
}
|
||||
|
||||
func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0)
|
||||
r1, _, e1 := syscall.SyscallN(procLookupPrivilegeNameW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
@@ -221,19 +183,19 @@ func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err err
|
||||
}
|
||||
|
||||
func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
|
||||
r1, _, e1 := syscall.SyscallN(procLookupPrivilegeValueW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) {
|
||||
func openThreadToken(thread windows.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) {
|
||||
var _p0 uint32
|
||||
if openAsSelf {
|
||||
_p0 = 1
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0)
|
||||
r1, _, e1 := syscall.SyscallN(procOpenThreadToken.Addr(), uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
@@ -241,14 +203,14 @@ func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool,
|
||||
}
|
||||
|
||||
func revertToSelf() (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0)
|
||||
r1, _, e1 := syscall.SyscallN(procRevertToSelf.Addr())
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
|
||||
func backupRead(h windows.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
|
||||
var _p0 *byte
|
||||
if len(b) > 0 {
|
||||
_p0 = &b[0]
|
||||
@@ -261,14 +223,14 @@ func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, proce
|
||||
if processSecurity {
|
||||
_p2 = 1
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
|
||||
r1, _, e1 := syscall.SyscallN(procBackupRead.Addr(), uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
|
||||
func backupWrite(h windows.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
|
||||
var _p0 *byte
|
||||
if len(b) > 0 {
|
||||
_p0 = &b[0]
|
||||
@@ -281,39 +243,39 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p
|
||||
if processSecurity {
|
||||
_p2 = 1
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
|
||||
r1, _, e1 := syscall.SyscallN(procBackupWrite.Addr(), uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0)
|
||||
func cancelIoEx(file windows.Handle, o *windows.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.SyscallN(procCancelIoEx.Addr(), uintptr(file), uintptr(unsafe.Pointer(o)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0)
|
||||
func connectNamedPipe(pipe windows.Handle, o *windows.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.SyscallN(procConnectNamedPipe.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(o)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0)
|
||||
newport = syscall.Handle(r0)
|
||||
func createIoCompletionPort(file windows.Handle, port windows.Handle, key uintptr, threadCount uint32) (newport windows.Handle, err error) {
|
||||
r0, _, e1 := syscall.SyscallN(procCreateIoCompletionPort.Addr(), uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount))
|
||||
newport = windows.Handle(r0)
|
||||
if newport == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
|
||||
func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *windows.SecurityAttributes) (handle windows.Handle, err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
@@ -322,96 +284,93 @@ func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances ui
|
||||
return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa)
|
||||
}
|
||||
|
||||
func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0)
|
||||
handle = syscall.Handle(r0)
|
||||
if handle == syscall.InvalidHandle {
|
||||
func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *windows.SecurityAttributes) (handle windows.Handle, err error) {
|
||||
r0, _, e1 := syscall.SyscallN(procCreateNamedPipeW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)))
|
||||
handle = windows.Handle(r0)
|
||||
if handle == windows.InvalidHandle {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getCurrentThread() (h syscall.Handle) {
|
||||
r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0)
|
||||
h = syscall.Handle(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0)
|
||||
func disconnectNamedPipe(pipe windows.Handle) (err error) {
|
||||
r1, _, e1 := syscall.SyscallN(procDisconnectNamedPipe.Addr(), uintptr(pipe))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0)
|
||||
func getCurrentThread() (h windows.Handle) {
|
||||
r0, _, _ := syscall.SyscallN(procGetCurrentThread.Addr())
|
||||
h = windows.Handle(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func getNamedPipeHandleState(pipe windows.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) {
|
||||
r1, _, e1 := syscall.SyscallN(procGetNamedPipeHandleStateW.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0)
|
||||
func getNamedPipeInfo(pipe windows.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) {
|
||||
r1, _, e1 := syscall.SyscallN(procGetNamedPipeInfo.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func localAlloc(uFlags uint32, length uint32) (ptr uintptr) {
|
||||
r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0)
|
||||
ptr = uintptr(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func localFree(mem uintptr) {
|
||||
syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0)
|
||||
return
|
||||
}
|
||||
|
||||
func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0)
|
||||
func getQueuedCompletionStatus(port windows.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) {
|
||||
r1, _, e1 := syscall.SyscallN(procGetQueuedCompletionStatus.Addr(), uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) {
|
||||
r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0)
|
||||
func setFileCompletionNotificationModes(h windows.Handle, flags uint8) (err error) {
|
||||
r1, _, e1 := syscall.SyscallN(procSetFileCompletionNotificationModes.Addr(), uintptr(h), uintptr(flags))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ntCreateNamedPipeFile(pipe *windows.Handle, access ntAccessMask, oa *objectAttributes, iosb *ioStatusBlock, share ntFileShareMode, disposition ntFileCreationDisposition, options ntFileOptions, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) {
|
||||
r0, _, _ := syscall.SyscallN(procNtCreateNamedPipeFile.Addr(), uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)))
|
||||
status = ntStatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) {
|
||||
r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0)
|
||||
r0, _, _ := syscall.SyscallN(procRtlDefaultNpAcl.Addr(), uintptr(unsafe.Pointer(dacl)))
|
||||
status = ntStatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) {
|
||||
r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0)
|
||||
r0, _, _ := syscall.SyscallN(procRtlDosPathNameToNtPathName_U.Addr(), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved))
|
||||
status = ntStatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlNtStatusToDosError(status ntStatus) (winerr error) {
|
||||
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
|
||||
r0, _, _ := syscall.SyscallN(procRtlNtStatusToDosErrorNoTeb.Addr(), uintptr(status))
|
||||
if r0 != 0 {
|
||||
winerr = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) {
|
||||
func wsaGetOverlappedResult(h windows.Handle, o *windows.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) {
|
||||
var _p0 uint32
|
||||
if wait {
|
||||
_p0 = 1
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0)
|
||||
r1, _, e1 := syscall.SyscallN(procWSAGetOverlappedResult.Addr(), uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
|
||||
8
vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go
generated
vendored
8
vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go
generated
vendored
@@ -49,16 +49,16 @@ func ShiftNBytesLeft(dst, x []byte, n int) {
|
||||
dst = append(dst, make([]byte, n/8)...)
|
||||
}
|
||||
|
||||
// XorBytesMut assumes equal input length, replaces X with X XOR Y
|
||||
// XorBytesMut replaces X with X XOR Y. len(X) must be >= len(Y).
|
||||
func XorBytesMut(X, Y []byte) {
|
||||
for i := 0; i < len(X); i++ {
|
||||
for i := 0; i < len(Y); i++ {
|
||||
X[i] ^= Y[i]
|
||||
}
|
||||
}
|
||||
|
||||
// XorBytes assumes equal input length, puts X XOR Y into Z
|
||||
// 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(X); i++ {
|
||||
for i := 0; i < len(Y); i++ {
|
||||
Z[i] = X[i] ^ Y[i]
|
||||
}
|
||||
}
|
||||
|
||||
54
vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go
generated
vendored
54
vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go
generated
vendored
@@ -18,8 +18,9 @@ import (
|
||||
"crypto/cipher"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"github.com/ProtonMail/go-crypto/internal/byteutil"
|
||||
"math/bits"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/internal/byteutil"
|
||||
)
|
||||
|
||||
type ocb struct {
|
||||
@@ -108,8 +109,10 @@ func (o *ocb) Seal(dst, nonce, plaintext, adata []byte) []byte {
|
||||
if len(nonce) > o.nonceSize {
|
||||
panic("crypto/ocb: Incorrect nonce length given to OCB")
|
||||
}
|
||||
ret, out := byteutil.SliceForAppend(dst, len(plaintext)+o.tagSize)
|
||||
o.crypt(enc, out, nonce, adata, plaintext)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -121,12 +124,10 @@ func (o *ocb) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) {
|
||||
return nil, ocbError("Ciphertext shorter than tag length")
|
||||
}
|
||||
sep := len(ciphertext) - o.tagSize
|
||||
ret, out := byteutil.SliceForAppend(dst, len(ciphertext))
|
||||
ret, out := byteutil.SliceForAppend(dst, sep)
|
||||
ciphertextData := ciphertext[:sep]
|
||||
tag := ciphertext[sep:]
|
||||
o.crypt(dec, out, nonce, adata, ciphertextData)
|
||||
if subtle.ConstantTimeCompare(ret[sep:], tag) == 1 {
|
||||
ret = ret[:sep]
|
||||
tag := o.crypt(dec, out, nonce, adata, ciphertextData)
|
||||
if subtle.ConstantTimeCompare(tag, ciphertext[sep:]) == 1 {
|
||||
return ret, nil
|
||||
}
|
||||
for i := range out {
|
||||
@@ -136,7 +137,8 @@ func (o *ocb) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
// On instruction enc (resp. dec), crypt is the encrypt (resp. decrypt)
|
||||
// function. It returns the resulting plain/ciphertext with the tag appended.
|
||||
// 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
|
||||
@@ -153,7 +155,7 @@ func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte {
|
||||
truncatedNonce := make([]byte, len(nonce))
|
||||
copy(truncatedNonce, nonce)
|
||||
truncatedNonce[len(truncatedNonce)-1] &= 192
|
||||
Ktop := make([]byte, blockSize)
|
||||
var Ktop []byte
|
||||
if bytes.Equal(truncatedNonce, o.reusableKtop.noncePrefix) {
|
||||
Ktop = o.reusableKtop.Ktop
|
||||
} else {
|
||||
@@ -193,13 +195,14 @@ func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte {
|
||||
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]
|
||||
byteutil.XorBytes(blockY, blockX, offset)
|
||||
switch instruction {
|
||||
case enc:
|
||||
byteutil.XorBytesMut(checksum, blockX)
|
||||
byteutil.XorBytes(blockY, blockX, offset)
|
||||
o.block.Encrypt(blockY, blockY)
|
||||
byteutil.XorBytesMut(blockY, offset)
|
||||
byteutil.XorBytesMut(checksum, blockX)
|
||||
case dec:
|
||||
byteutil.XorBytes(blockY, blockX, offset)
|
||||
o.block.Decrypt(blockY, blockY)
|
||||
byteutil.XorBytesMut(blockY, offset)
|
||||
byteutil.XorBytesMut(checksum, blockY)
|
||||
@@ -215,31 +218,24 @@ func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte {
|
||||
o.block.Encrypt(pad, offset)
|
||||
chunkX := X[blockSize*m:]
|
||||
chunkY := Y[blockSize*m : len(X)]
|
||||
byteutil.XorBytes(chunkY, chunkX, pad[:len(chunkX)])
|
||||
// P_* || bit(1) || zeroes(127) - len(P_*)
|
||||
switch instruction {
|
||||
case enc:
|
||||
paddedY := append(chunkX, byte(128))
|
||||
paddedY = append(paddedY, make([]byte, blockSize-len(chunkX)-1)...)
|
||||
byteutil.XorBytesMut(checksum, paddedY)
|
||||
byteutil.XorBytesMut(checksum, chunkX)
|
||||
checksum[len(chunkX)] ^= 128
|
||||
byteutil.XorBytes(chunkY, chunkX, pad[:len(chunkX)])
|
||||
// P_* || bit(1) || zeroes(127) - len(P_*)
|
||||
case dec:
|
||||
paddedX := append(chunkY, byte(128))
|
||||
paddedX = append(paddedX, make([]byte, blockSize-len(chunkY)-1)...)
|
||||
byteutil.XorBytesMut(checksum, paddedX)
|
||||
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))
|
||||
copy(Y[blockSize*m+len(chunkY):], tag[:o.tagSize])
|
||||
} else {
|
||||
byteutil.XorBytes(tag, checksum, offset)
|
||||
byteutil.XorBytesMut(tag, o.mask.lDol)
|
||||
o.block.Encrypt(tag, tag)
|
||||
byteutil.XorBytesMut(tag, o.hash(adata))
|
||||
copy(Y[blockSize*m:], tag[:o.tagSize])
|
||||
}
|
||||
return Y
|
||||
return tag[:o.tagSize]
|
||||
}
|
||||
|
||||
// This hash function is used to compute the tag. Per design, on empty input it
|
||||
|
||||
56
vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go
generated
vendored
56
vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go
generated
vendored
@@ -23,7 +23,7 @@ import (
|
||||
// Headers
|
||||
//
|
||||
// base64-encoded Bytes
|
||||
// '=' base64 encoded checksum
|
||||
// '=' base64 encoded checksum (optional) not checked anymore
|
||||
// -----END Type-----
|
||||
//
|
||||
// where Headers is a possibly empty sequence of Key: Value lines.
|
||||
@@ -40,36 +40,15 @@ type Block struct {
|
||||
|
||||
var ArmorCorrupt error = errors.StructuralError("armor invalid")
|
||||
|
||||
const crc24Init = 0xb704ce
|
||||
const crc24Poly = 0x1864cfb
|
||||
const crc24Mask = 0xffffff
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
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 and records the expected CRC value.
|
||||
// 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
|
||||
crc uint32
|
||||
crcSet bool
|
||||
}
|
||||
|
||||
func (l *lineReader) Read(p []byte) (n int, err error) {
|
||||
@@ -98,26 +77,9 @@ func (l *lineReader) Read(p []byte) (n int, err error) {
|
||||
|
||||
if len(line) == 5 && line[0] == '=' {
|
||||
// This is the checksum line
|
||||
var expectedBytes [3]byte
|
||||
var m int
|
||||
m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:])
|
||||
if m != 3 || err != nil {
|
||||
return
|
||||
}
|
||||
l.crc = uint32(expectedBytes[0])<<16 |
|
||||
uint32(expectedBytes[1])<<8 |
|
||||
uint32(expectedBytes[2])
|
||||
|
||||
line, _, err = l.in.ReadLine()
|
||||
if err != nil && err != io.EOF {
|
||||
return
|
||||
}
|
||||
if !bytes.HasPrefix(line, armorEnd) {
|
||||
return 0, ArmorCorrupt
|
||||
}
|
||||
// Don't check the checksum
|
||||
|
||||
l.eof = true
|
||||
l.crcSet = true
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
@@ -138,23 +100,14 @@ func (l *lineReader) Read(p []byte) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// openpgpReader passes Read calls to the underlying base64 decoder, but keeps
|
||||
// a running CRC of the resulting data and checks the CRC against the value
|
||||
// found by the lineReader at EOF.
|
||||
// openpgpReader passes Read calls to the underlying base64 decoder.
|
||||
type openpgpReader struct {
|
||||
lReader *lineReader
|
||||
b64Reader io.Reader
|
||||
currentCRC uint32
|
||||
}
|
||||
|
||||
func (r *openpgpReader) Read(p []byte) (n int, err error) {
|
||||
n, err = r.b64Reader.Read(p)
|
||||
r.currentCRC = crc24(r.currentCRC, p[:n])
|
||||
|
||||
if err == io.EOF && r.lReader.crcSet && r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
|
||||
return 0, ArmorCorrupt
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -222,7 +175,6 @@ TryNextBlock:
|
||||
}
|
||||
|
||||
p.lReader.in = r
|
||||
p.oReader.currentCRC = crc24Init
|
||||
p.oReader.lReader = &p.lReader
|
||||
p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader)
|
||||
p.Body = &p.oReader
|
||||
|
||||
57
vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go
generated
vendored
57
vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go
generated
vendored
@@ -7,6 +7,7 @@ package armor
|
||||
import (
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"sort"
|
||||
)
|
||||
|
||||
var armorHeaderSep = []byte(": ")
|
||||
@@ -14,6 +15,23 @@ 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 {
|
||||
@@ -103,11 +121,14 @@ type encoding struct {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -118,6 +139,7 @@ func (e *encoding) Close() (err error) {
|
||||
}
|
||||
e.breaker.Close()
|
||||
|
||||
if e.crcEnabled {
|
||||
var checksumBytes [3]byte
|
||||
checksumBytes[0] = byte(e.crc >> 16)
|
||||
checksumBytes[1] = byte(e.crc >> 8)
|
||||
@@ -128,18 +150,25 @@ func (e *encoding) Close() (err error) {
|
||||
|
||||
return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
|
||||
}
|
||||
return writeSlices(e.out, newline, armorEnd, e.blockType, armorEndOfLine)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline)
|
||||
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
|
||||
}
|
||||
@@ -153,9 +182,25 @@ func Encode(out io.Writer, blockType string, headers map[string]string) (w io.Wr
|
||||
e := &encoding{
|
||||
out: out,
|
||||
breaker: newLineBreaker(out, 64),
|
||||
crc: crc24Init,
|
||||
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)
|
||||
}
|
||||
|
||||
12
vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go
generated
vendored
12
vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go
generated
vendored
@@ -30,8 +30,12 @@ func writeCanonical(cw io.Writer, buf []byte, s *int) (int, error) {
|
||||
if c == '\r' {
|
||||
*s = 1
|
||||
} else if c == '\n' {
|
||||
cw.Write(buf[start:i])
|
||||
cw.Write(newline)
|
||||
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:
|
||||
@@ -39,7 +43,9 @@ func writeCanonical(cw io.Writer, buf []byte, s *int) (int, error) {
|
||||
}
|
||||
}
|
||||
|
||||
cw.Write(buf[start:])
|
||||
if _, err := cw.Write(buf[start:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(buf), nil
|
||||
}
|
||||
|
||||
|
||||
6
vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go
generated
vendored
6
vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go
generated
vendored
@@ -163,13 +163,9 @@ func buildKey(pub *PublicKey, zb []byte, curveOID, fingerprint []byte, stripLead
|
||||
if _, err := param.Write([]byte("Anonymous Sender ")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// For v5 keys, the 20 leftmost octets of the fingerprint are used.
|
||||
if _, err := param.Write(fingerprint[:20]); err != nil {
|
||||
if _, err := param.Write(fingerprint[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if param.Len()-len(curveOID) != 45 {
|
||||
return nil, errors.New("ecdh: malformed KDF Param")
|
||||
}
|
||||
|
||||
// MB = Hash ( 00 || 00 || 00 || 01 || ZB || Param );
|
||||
h := pub.KDF.Hash.New()
|
||||
|
||||
115
vendor/github.com/ProtonMail/go-crypto/openpgp/ed25519/ed25519.go
generated
vendored
Normal file
115
vendor/github.com/ProtonMail/go-crypto/openpgp/ed25519/ed25519.go
generated
vendored
Normal 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
|
||||
}
|
||||
119
vendor/github.com/ProtonMail/go-crypto/openpgp/ed448/ed448.go
generated
vendored
Normal file
119
vendor/github.com/ProtonMail/go-crypto/openpgp/ed448/ed448.go
generated
vendored
Normal 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
|
||||
}
|
||||
100
vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go
generated
vendored
100
vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go
generated
vendored
@@ -6,9 +6,22 @@
|
||||
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
|
||||
@@ -17,6 +30,34 @@ 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
|
||||
@@ -41,9 +82,6 @@ func (b SignatureError) Error() string {
|
||||
return "openpgp: invalid signature: " + string(b)
|
||||
}
|
||||
|
||||
var ErrMDCHashMismatch error = SignatureError("MDC hash mismatch")
|
||||
var ErrMDCMissing error = SignatureError("MDC packet not found")
|
||||
|
||||
type signatureExpiredError int
|
||||
|
||||
func (se signatureExpiredError) Error() string {
|
||||
@@ -58,6 +96,14 @@ 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
|
||||
@@ -92,12 +138,24 @@ func (keyRevokedError) Error() string {
|
||||
|
||||
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
|
||||
@@ -114,3 +172,39 @@ 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)
|
||||
}
|
||||
|
||||
12
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go
generated
vendored
12
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go
generated
vendored
@@ -51,24 +51,14 @@ func (sk CipherFunction) Id() uint8 {
|
||||
return uint8(sk)
|
||||
}
|
||||
|
||||
var keySizeByID = map[uint8]int{
|
||||
TripleDES.Id(): 24,
|
||||
CAST5.Id(): cast5.KeySize,
|
||||
AES128.Id(): 16,
|
||||
AES192.Id(): 24,
|
||||
AES256.Id(): 32,
|
||||
}
|
||||
|
||||
// KeySize returns the key size, in bytes, of cipher.
|
||||
func (cipher CipherFunction) KeySize() int {
|
||||
switch cipher {
|
||||
case TripleDES:
|
||||
return 24
|
||||
case CAST5:
|
||||
return cast5.KeySize
|
||||
case AES128:
|
||||
return 16
|
||||
case AES192:
|
||||
case AES192, TripleDES:
|
||||
return 24
|
||||
case AES256:
|
||||
return 32
|
||||
|
||||
9
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve_info.go
generated
vendored
9
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve_info.go
generated
vendored
@@ -4,11 +4,14 @@ 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
|
||||
@@ -42,19 +45,19 @@ var Curves = []CurveInfo{
|
||||
},
|
||||
{
|
||||
// Curve25519
|
||||
GenName: "Curve25519",
|
||||
GenName: Curve25519GenName,
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}),
|
||||
Curve: NewCurve25519(),
|
||||
},
|
||||
{
|
||||
// X448
|
||||
// x448
|
||||
GenName: "Curve448",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x65, 0x6F}),
|
||||
Curve: NewX448(),
|
||||
},
|
||||
{
|
||||
// Ed25519
|
||||
GenName: "Curve25519",
|
||||
GenName: Curve25519GenName,
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01}),
|
||||
Curve: NewEd25519(),
|
||||
},
|
||||
|
||||
10
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed25519.go
generated
vendored
10
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed25519.go
generated
vendored
@@ -2,6 +2,7 @@
|
||||
package ecc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/subtle"
|
||||
"io"
|
||||
|
||||
@@ -90,7 +91,14 @@ func (c *ed25519) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) {
|
||||
}
|
||||
|
||||
func getEd25519Sk(publicKey, privateKey []byte) ed25519lib.PrivateKey {
|
||||
return append(privateKey, publicKey...)
|
||||
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) {
|
||||
|
||||
10
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed448.go
generated
vendored
10
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed448.go
generated
vendored
@@ -2,6 +2,7 @@
|
||||
package ecc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/subtle"
|
||||
"io"
|
||||
|
||||
@@ -84,7 +85,14 @@ func (c *ed448) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) {
|
||||
}
|
||||
|
||||
func getEd448Sk(publicKey, privateKey []byte) ed448lib.PrivateKey {
|
||||
return append(privateKey, publicKey...)
|
||||
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) {
|
||||
|
||||
119
vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go
generated
vendored
119
vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go
generated
vendored
@@ -15,11 +15,15 @@ import (
|
||||
|
||||
"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
|
||||
@@ -36,8 +40,10 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
|
||||
return nil, err
|
||||
}
|
||||
primary := packet.NewSignerPrivateKey(creationTime, primaryPrivRaw)
|
||||
if config != nil && config.V5Keys {
|
||||
primary.UpgradeToV5()
|
||||
if config.V6() {
|
||||
if err := primary.UpgradeToV6(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
e := &Entity{
|
||||
@@ -45,9 +51,25 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
|
||||
PrivateKey: primary,
|
||||
Identities: make(map[string]*Identity),
|
||||
Subkeys: []Subkey{},
|
||||
Signatures: []*packet.Signature{},
|
||||
}
|
||||
|
||||
err = e.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs)
|
||||
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
|
||||
}
|
||||
@@ -65,32 +87,19 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
|
||||
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)
|
||||
return t.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs, !config.V6())
|
||||
}
|
||||
|
||||
func (t *Entity) addUserId(name, comment, email string, config *packet.Config, creationTime time.Time, keyLifetimeSecs uint32) error {
|
||||
uid := packet.NewUserId(name, comment, email)
|
||||
if uid == nil {
|
||||
return errors.InvalidArgumentError("user id field contained invalid characters")
|
||||
}
|
||||
func writeKeyProperties(selfSignature *packet.Signature, creationTime time.Time, keyLifetimeSecs uint32, config *packet.Config) error {
|
||||
advertiseAead := config.AEAD() != nil
|
||||
|
||||
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)
|
||||
selfSignature.CreationTime = creationTime
|
||||
selfSignature.KeyLifetimeSecs = &keyLifetimeSecs
|
||||
selfSignature.IsPrimaryId = &isPrimaryId
|
||||
selfSignature.FlagsValid = true
|
||||
selfSignature.FlagSign = true
|
||||
selfSignature.FlagCertify = true
|
||||
selfSignature.SEIPDv1 = true // true by default, see 5.8 vs. 5.14
|
||||
selfSignature.SEIPDv2 = config.AEAD() != nil
|
||||
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.
|
||||
@@ -119,7 +128,9 @@ func (t *Entity) addUserId(name, comment, email string, config *packet.Config, c
|
||||
selfSignature.PreferredCompression = append(selfSignature.PreferredCompression, uint8(config.Compression()))
|
||||
}
|
||||
|
||||
// And for DefaultMode.
|
||||
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))
|
||||
@@ -131,6 +142,30 @@ func (t *Entity) addUserId(name, comment, email string, config *packet.Config, c
|
||||
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)
|
||||
@@ -158,8 +193,10 @@ func (e *Entity) AddSigningSubkey(config *packet.Config) error {
|
||||
}
|
||||
sub := packet.NewSignerPrivateKey(creationTime, subPrivRaw)
|
||||
sub.IsSubkey = true
|
||||
if config != nil && config.V5Keys {
|
||||
sub.UpgradeToV5()
|
||||
if config.V6() {
|
||||
if err := sub.UpgradeToV6(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
subkey := Subkey{
|
||||
@@ -203,8 +240,10 @@ func (e *Entity) addEncryptionSubkey(config *packet.Config, creationTime time.Ti
|
||||
}
|
||||
sub := packet.NewDecrypterPrivateKey(creationTime, subPrivRaw)
|
||||
sub.IsSubkey = true
|
||||
if config != nil && config.V5Keys {
|
||||
sub.UpgradeToV5()
|
||||
if config.V6() {
|
||||
if err := sub.UpgradeToV6(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
subkey := Subkey{
|
||||
@@ -242,6 +281,11 @@ func newSigner(config *packet.Config) (signer interface{}, err error) {
|
||||
}
|
||||
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")
|
||||
@@ -263,6 +307,18 @@ func newSigner(config *packet.Config) (signer interface{}, err error) {
|
||||
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")
|
||||
}
|
||||
@@ -285,6 +341,13 @@ func newDecrypter(config *packet.Config) (decrypter interface{}, err error) {
|
||||
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,
|
||||
@@ -294,6 +357,10 @@ func newDecrypter(config *packet.Config) (decrypter interface{}, err error) {
|
||||
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")
|
||||
}
|
||||
@@ -302,7 +369,7 @@ func newDecrypter(config *packet.Config) (decrypter interface{}, err error) {
|
||||
var bigOne = big.NewInt(1)
|
||||
|
||||
// generateRSAKeyWithPrimes generates a multi-prime RSA keypair of the
|
||||
// given bit size, using the given random source and prepopulated primes.
|
||||
// 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
|
||||
|
||||
111
vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go
generated
vendored
111
vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go
generated
vendored
@@ -6,6 +6,7 @@ package openpgp
|
||||
|
||||
import (
|
||||
goerrors "errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
@@ -29,6 +30,8 @@ type Entity struct {
|
||||
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
|
||||
@@ -120,12 +123,12 @@ func shouldPreferIdentity(existingId, potentialNewId *Identity) bool {
|
||||
// given Entity.
|
||||
func (e *Entity) EncryptionKey(now time.Time) (Key, bool) {
|
||||
// Fail to find any encryption key if the...
|
||||
i := e.PrimaryIdentity()
|
||||
if e.PrimaryKey.KeyExpired(i.SelfSignature, now) || // primary key has expired
|
||||
i.SelfSignature == nil || // user ID has no self-signature
|
||||
i.SelfSignature.SigExpired(now) || // user ID self-signature has expired
|
||||
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
|
||||
i.Revoked(now) { // user ID 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
|
||||
}
|
||||
|
||||
@@ -152,9 +155,9 @@ func (e *Entity) EncryptionKey(now time.Time) (Key, bool) {
|
||||
|
||||
// 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 i.SelfSignature.FlagsValid && i.SelfSignature.FlagEncryptCommunications &&
|
||||
if primarySelfSignature.FlagsValid && primarySelfSignature.FlagEncryptCommunications &&
|
||||
e.PrimaryKey.PubKeyAlgo.CanEncrypt() {
|
||||
return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature, e.Revocations}, true
|
||||
return Key{e, e.PrimaryKey, e.PrivateKey, primarySelfSignature, e.Revocations}, true
|
||||
}
|
||||
|
||||
return Key{}, false
|
||||
@@ -186,12 +189,12 @@ func (e *Entity) SigningKeyById(now time.Time, id uint64) (Key, bool) {
|
||||
|
||||
func (e *Entity) signingKeyByIdUsage(now time.Time, id uint64, flags int) (Key, bool) {
|
||||
// Fail to find any signing key if the...
|
||||
i := e.PrimaryIdentity()
|
||||
if e.PrimaryKey.KeyExpired(i.SelfSignature, now) || // primary key has expired
|
||||
i.SelfSignature == nil || // user ID has no self-signature
|
||||
i.SelfSignature.SigExpired(now) || // user ID self-signature has expired
|
||||
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
|
||||
i.Revoked(now) { // user ID 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
|
||||
}
|
||||
|
||||
@@ -220,12 +223,12 @@ func (e *Entity) signingKeyByIdUsage(now time.Time, id uint64, flags int) (Key,
|
||||
|
||||
// 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 i.SelfSignature.FlagsValid &&
|
||||
(flags&packet.KeyFlagCertify == 0 || i.SelfSignature.FlagCertify) &&
|
||||
(flags&packet.KeyFlagSign == 0 || i.SelfSignature.FlagSign) &&
|
||||
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, i.SelfSignature, e.Revocations}, true
|
||||
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
|
||||
@@ -271,7 +274,7 @@ func (e *Entity) EncryptPrivateKeys(passphrase []byte, config *packet.Config) er
|
||||
return packet.EncryptPrivateKeys(keysToEncrypt, passphrase, config)
|
||||
}
|
||||
|
||||
// DecryptPrivateKeys decrypts all encrypted keys in the entitiy with the given passphrase.
|
||||
// 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 {
|
||||
@@ -318,8 +321,7 @@ type EntityList []*Entity
|
||||
func (el EntityList) KeysById(id uint64) (keys []Key) {
|
||||
for _, e := range el {
|
||||
if e.PrimaryKey.KeyId == id {
|
||||
ident := e.PrimaryIdentity()
|
||||
selfSig := ident.SelfSignature
|
||||
selfSig, _ := e.PrimarySelfSignature()
|
||||
keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig, e.Revocations})
|
||||
}
|
||||
|
||||
@@ -441,7 +443,6 @@ func readToNextPublicKey(packets *packet.Reader) (err error) {
|
||||
return
|
||||
} else if err != nil {
|
||||
if _, ok := err.(errors.UnsupportedError); ok {
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
return
|
||||
@@ -479,6 +480,7 @@ func ReadEntity(packets *packet.Reader) (*Entity, error) {
|
||||
}
|
||||
|
||||
var revocations []*packet.Signature
|
||||
var directSignatures []*packet.Signature
|
||||
EachPacket:
|
||||
for {
|
||||
p, err := packets.Next()
|
||||
@@ -497,9 +499,7 @@ EachPacket:
|
||||
if pkt.SigType == packet.SigTypeKeyRevocation {
|
||||
revocations = append(revocations, pkt)
|
||||
} else if pkt.SigType == packet.SigTypeDirectSignature {
|
||||
// TODO: RFC4880 5.2.1 permits signatures
|
||||
// directly on keys (eg. to bind additional
|
||||
// revocation keys).
|
||||
directSignatures = append(directSignatures, pkt)
|
||||
}
|
||||
// Else, ignoring the signature as it does not follow anything
|
||||
// we would know to attach it to.
|
||||
@@ -522,12 +522,39 @@ EachPacket:
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
// we ignore unknown packets
|
||||
// we ignore unknown packets.
|
||||
}
|
||||
}
|
||||
|
||||
if len(e.Identities) == 0 {
|
||||
return nil, errors.StructuralError("entity without any identities")
|
||||
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 {
|
||||
@@ -672,6 +699,12 @@ func (e *Entity) serializePrivate(w io.Writer, config *packet.Config, reSign boo
|
||||
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 {
|
||||
@@ -738,6 +771,12 @@ func (e *Entity) Serialize(w io.Writer) error {
|
||||
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 {
|
||||
@@ -840,3 +879,23 @@ func (e *Entity) RevokeSubkey(sk *Subkey, reason packet.ReasonForRevocation, rea
|
||||
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
|
||||
}
|
||||
|
||||
6
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go
generated
vendored
6
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go
generated
vendored
@@ -37,7 +37,7 @@ func (conf *AEADConfig) Mode() AEADMode {
|
||||
|
||||
// ChunkSizeByte returns the byte indicating the chunk size. The effective
|
||||
// chunk size is computed with the formula uint64(1) << (chunkSizeByte + 6)
|
||||
// limit to 16 = 4 MiB
|
||||
// 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 {
|
||||
@@ -49,8 +49,8 @@ func (conf *AEADConfig) ChunkSizeByte() byte {
|
||||
switch {
|
||||
case exponent < 6:
|
||||
exponent = 6
|
||||
case exponent > 16:
|
||||
exponent = 16
|
||||
case exponent > 22:
|
||||
exponent = 22
|
||||
}
|
||||
|
||||
return byte(exponent - 6)
|
||||
|
||||
110
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go
generated
vendored
110
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go
generated
vendored
@@ -3,7 +3,6 @@
|
||||
package packet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
@@ -15,12 +14,11 @@ import (
|
||||
type aeadCrypter struct {
|
||||
aead cipher.AEAD
|
||||
chunkSize int
|
||||
initialNonce []byte
|
||||
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
|
||||
buffer bytes.Buffer // Buffered bytes across chunks
|
||||
}
|
||||
|
||||
// computeNonce takes the incremental index and computes an eXclusive OR with
|
||||
@@ -28,12 +26,12 @@ type aeadCrypter struct {
|
||||
// 5.16.1 and 5.16.2). It returns the resulting nonce.
|
||||
func (wo *aeadCrypter) computeNextNonce() (nonce []byte) {
|
||||
if wo.packetTag == packetTypeSymmetricallyEncryptedIntegrityProtected {
|
||||
return append(wo.initialNonce, wo.chunkIndex...)
|
||||
return wo.nonce
|
||||
}
|
||||
|
||||
nonce = make([]byte, len(wo.initialNonce))
|
||||
copy(nonce, wo.initialNonce)
|
||||
offset := len(wo.initialNonce) - 8
|
||||
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]
|
||||
}
|
||||
@@ -62,8 +60,9 @@ func (wo *aeadCrypter) incrementIndex() error {
|
||||
type aeadDecrypter struct {
|
||||
aeadCrypter // Embedded ciphertext opener
|
||||
reader io.Reader // 'reader' is a partialLengthReader
|
||||
chunkBytes []byte
|
||||
peekedBytes []byte // Used to detect last chunk
|
||||
eof bool
|
||||
buffer []byte // Buffered decrypted bytes
|
||||
}
|
||||
|
||||
// Read decrypts bytes and reads them into dst. It decrypts when necessary and
|
||||
@@ -71,51 +70,45 @@ type aeadDecrypter struct {
|
||||
// and an error.
|
||||
func (ar *aeadDecrypter) Read(dst []byte) (n int, err error) {
|
||||
// Return buffered plaintext bytes from previous calls
|
||||
if ar.buffer.Len() > 0 {
|
||||
return ar.buffer.Read(dst)
|
||||
}
|
||||
|
||||
// Return EOF if we've previously validated the final tag
|
||||
if ar.eof {
|
||||
return 0, io.EOF
|
||||
if len(ar.buffer) > 0 {
|
||||
n = copy(dst, ar.buffer)
|
||||
ar.buffer = ar.buffer[n:]
|
||||
return
|
||||
}
|
||||
|
||||
// Read a chunk
|
||||
tagLen := ar.aead.Overhead()
|
||||
cipherChunkBuf := new(bytes.Buffer)
|
||||
_, errRead := io.CopyN(cipherChunkBuf, ar.reader, int64(ar.chunkSize+tagLen))
|
||||
cipherChunk := cipherChunkBuf.Bytes()
|
||||
if errRead != nil && errRead != io.EOF {
|
||||
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
|
||||
}
|
||||
decrypted, errChunk := ar.openChunk(cipherChunk)
|
||||
|
||||
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
|
||||
if len(dst) < len(decrypted) {
|
||||
n = copy(dst, decrypted[:len(dst)])
|
||||
ar.buffer.Write(decrypted[len(dst):])
|
||||
} else {
|
||||
n = copy(dst, decrypted)
|
||||
}
|
||||
|
||||
// Check final authentication tag
|
||||
if errRead == io.EOF {
|
||||
errChunk := ar.validateFinalTag(ar.peekedBytes)
|
||||
if errChunk != nil {
|
||||
return n, errChunk
|
||||
}
|
||||
ar.eof = true // Mark EOF for when we've returned all buffered data
|
||||
}
|
||||
ar.buffer = decrypted[n:]
|
||||
return
|
||||
}
|
||||
|
||||
// Close is noOp. The final authentication tag of the stream was already
|
||||
// checked in the last Read call. In the future, this function could be used to
|
||||
// wipe the reader and peeked, decrypted bytes, if necessary.
|
||||
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
|
||||
}
|
||||
|
||||
@@ -123,22 +116,15 @@ func (ar *aeadDecrypter) Close() (err error) {
|
||||
// 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) {
|
||||
tagLen := ar.aead.Overhead()
|
||||
// Restore carried bytes from last call
|
||||
chunkExtra := append(ar.peekedBytes, data...)
|
||||
// 'chunk' contains encrypted bytes, followed by an authentication tag.
|
||||
chunk := chunkExtra[:len(chunkExtra)-tagLen]
|
||||
ar.peekedBytes = chunkExtra[len(chunkExtra)-tagLen:]
|
||||
|
||||
adata := ar.associatedData
|
||||
if ar.aeadCrypter.packetTag == packetTypeAEADEncrypted {
|
||||
adata = append(ar.associatedData, ar.chunkIndex...)
|
||||
}
|
||||
|
||||
nonce := ar.computeNextNonce()
|
||||
plainChunk, err := ar.aead.Open(nil, nonce, chunk, adata)
|
||||
plainChunk, err := ar.aead.Open(data[:0:len(data)], nonce, data, adata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.ErrAEADTagVerification
|
||||
}
|
||||
ar.bytesProcessed += len(plainChunk)
|
||||
if err = ar.aeadCrypter.incrementIndex(); err != nil {
|
||||
@@ -163,9 +149,8 @@ func (ar *aeadDecrypter) validateFinalTag(tag []byte) error {
|
||||
// ... and total number of encrypted octets
|
||||
adata = append(adata, amountBytes...)
|
||||
nonce := ar.computeNextNonce()
|
||||
_, err := ar.aead.Open(nil, nonce, tag, adata)
|
||||
if err != nil {
|
||||
return err
|
||||
if _, err := ar.aead.Open(nil, nonce, tag, adata); err != nil {
|
||||
return errors.ErrAEADTagVerification
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -175,21 +160,21 @@ func (ar *aeadDecrypter) validateFinalTag(tag []byte) error {
|
||||
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) {
|
||||
// Append plaintextBytes to existing buffered bytes
|
||||
n, err = aw.buffer.Write(plaintextBytes)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
// Encrypt and write chunks
|
||||
for aw.buffer.Len() >= aw.chunkSize {
|
||||
plainChunk := aw.buffer.Next(aw.chunkSize)
|
||||
encryptedChunk, err := aw.sealChunk(plainChunk)
|
||||
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
|
||||
}
|
||||
@@ -197,6 +182,8 @@ func (aw *aeadEncrypter) Write(plaintextBytes []byte) (n int, err error) {
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
aw.offset = 0
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -207,9 +194,8 @@ func (aw *aeadEncrypter) Write(plaintextBytes []byte) (n int, err error) {
|
||||
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.buffer.Len() > 0 || aw.bytesProcessed == 0 {
|
||||
plainChunk := aw.buffer.Bytes()
|
||||
lastEncryptedChunk, err := aw.sealChunk(plainChunk)
|
||||
if aw.offset > 0 || aw.bytesProcessed == 0 {
|
||||
lastEncryptedChunk, err := aw.sealChunk(aw.chunkBytes[:aw.offset])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -255,7 +241,7 @@ func (aw *aeadEncrypter) sealChunk(data []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
nonce := aw.computeNextNonce()
|
||||
encrypted := aw.aead.Seal(nil, nonce, data, adata)
|
||||
encrypted := aw.aead.Seal(data[:0], nonce, data, adata)
|
||||
aw.bytesProcessed += len(data)
|
||||
if err := aw.aeadCrypter.incrementIndex(); err != nil {
|
||||
return nil, err
|
||||
|
||||
12
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go
generated
vendored
12
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go
generated
vendored
@@ -65,24 +65,28 @@ 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()
|
||||
peekedBytes := make([]byte, tagLen)
|
||||
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())
|
||||
}
|
||||
chunkSize := decodeAEADChunkSize(ae.chunkSizeByte)
|
||||
|
||||
return &aeadDecrypter{
|
||||
aeadCrypter: aeadCrypter{
|
||||
aead: aead,
|
||||
chunkSize: chunkSize,
|
||||
initialNonce: ae.initialNonce,
|
||||
nonce: ae.initialNonce,
|
||||
associatedData: ae.associatedData(),
|
||||
chunkIndex: make([]byte, 8),
|
||||
packetTag: packetTypeAEADEncrypted,
|
||||
},
|
||||
reader: ae.Contents,
|
||||
peekedBytes: peekedBytes}, nil
|
||||
chunkBytes: chunkBytes,
|
||||
peekedBytes: peekedBytes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// associatedData for chunks: tag, version, cipher, mode, chunk size byte
|
||||
|
||||
75
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go
generated
vendored
75
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go
generated
vendored
@@ -8,9 +8,10 @@ import (
|
||||
"compress/bzip2"
|
||||
"compress/flate"
|
||||
"compress/zlib"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
// Compressed represents a compressed OpenPGP packet. The decompressed contents
|
||||
@@ -39,6 +40,37 @@ type CompressionConfig struct {
|
||||
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[:])
|
||||
@@ -50,11 +82,15 @@ func (c *Compressed) parse(r io.Reader) error {
|
||||
case 0:
|
||||
c.Body = r
|
||||
case 1:
|
||||
c.Body = flate.NewReader(r)
|
||||
c.Body = newDecompressionReader(r, flate.NewReader(r))
|
||||
case 2:
|
||||
c.Body, err = zlib.NewReader(r)
|
||||
decompressor, err := zlib.NewReader(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Body = newDecompressionReader(r, decompressor)
|
||||
case 3:
|
||||
c.Body = bzip2.NewReader(r)
|
||||
c.Body = newDecompressionReader(r, io.NopCloser(bzip2.NewReader(r)))
|
||||
default:
|
||||
err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
|
||||
}
|
||||
@@ -62,6 +98,16 @@ func (c *Compressed) parse(r io.Reader) error {
|
||||
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()
|
||||
@@ -123,3 +169,24 @@ func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *Compression
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
194
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go
generated
vendored
194
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go
generated
vendored
@@ -14,6 +14,34 @@ import (
|
||||
"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 {
|
||||
@@ -73,9 +101,16 @@ type Config struct {
|
||||
// **Note: using this option may break compatibility with other OpenPGP
|
||||
// implementations, as well as future versions of this library.**
|
||||
AEADConfig *AEADConfig
|
||||
// V5Keys configures version 5 key generation. If false, this package still
|
||||
// supports version 5 keys, but produces version 4 keys.
|
||||
V5Keys bool
|
||||
// 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
|
||||
@@ -104,12 +139,50 @@ type Config struct {
|
||||
// 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 {
|
||||
@@ -197,7 +270,7 @@ func (c *Config) S2K() *s2k.Config {
|
||||
return nil
|
||||
}
|
||||
// for backwards compatibility
|
||||
if c != nil && c.S2KCount > 0 && c.S2KConfig == nil {
|
||||
if c.S2KCount > 0 && c.S2KConfig == nil {
|
||||
return &s2k.Config{
|
||||
S2KCount: c.S2KCount,
|
||||
}
|
||||
@@ -233,6 +306,13 @@ func (c *Config) AllowUnauthenticatedMessages() bool {
|
||||
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
|
||||
@@ -246,3 +326,109 @@ func (c *Config) Notations() []*Notation {
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
7
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config_v5.go
generated
vendored
Normal file
7
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config_v5.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
//go:build !v5
|
||||
|
||||
package packet
|
||||
|
||||
func init() {
|
||||
V5Disabled = true
|
||||
}
|
||||
404
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go
generated
vendored
404
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go
generated
vendored
@@ -5,9 +5,11 @@
|
||||
package packet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/rsa"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"math/big"
|
||||
"strconv"
|
||||
@@ -16,32 +18,85 @@ import (
|
||||
"github.com/ProtonMail/go-crypto/openpgp/elgamal"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/x25519"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/x448"
|
||||
)
|
||||
|
||||
const encryptedKeyVersion = 3
|
||||
|
||||
// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
|
||||
// section 5.1.
|
||||
type EncryptedKey struct {
|
||||
Version int
|
||||
KeyId uint64
|
||||
KeyVersion int // v6
|
||||
KeyFingerprint []byte // v6
|
||||
Algo PublicKeyAlgorithm
|
||||
CipherFunc CipherFunction // only valid after a successful Decrypt for a v3 packet
|
||||
Key []byte // only valid after a successful Decrypt
|
||||
|
||||
encryptedMPI1, encryptedMPI2 encoding.Field
|
||||
ephemeralPublicX25519 *x25519.PublicKey // used for x25519
|
||||
ephemeralPublicX448 *x448.PublicKey // used for x448
|
||||
encryptedSession []byte // used for x25519 and x448
|
||||
}
|
||||
|
||||
func (e *EncryptedKey) parse(r io.Reader) (err error) {
|
||||
var buf [10]byte
|
||||
_, err = readFull(r, buf[:])
|
||||
var buf [8]byte
|
||||
_, err = readFull(r, buf[:versionSize])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if buf[0] != encryptedKeyVersion {
|
||||
e.Version = int(buf[0])
|
||||
if e.Version != 3 && e.Version != 6 {
|
||||
return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
|
||||
}
|
||||
e.KeyId = binary.BigEndian.Uint64(buf[1:9])
|
||||
e.Algo = PublicKeyAlgorithm(buf[9])
|
||||
if e.Version == 6 {
|
||||
//Read a one-octet size of the following two fields.
|
||||
if _, err = readFull(r, buf[:1]); err != nil {
|
||||
return
|
||||
}
|
||||
// The size may also be zero, and the key version and
|
||||
// fingerprint omitted for an "anonymous recipient"
|
||||
if buf[0] != 0 {
|
||||
// non-anonymous case
|
||||
_, err = readFull(r, buf[:versionSize])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
e.KeyVersion = int(buf[0])
|
||||
if e.KeyVersion != 4 && e.KeyVersion != 6 {
|
||||
return errors.UnsupportedError("unknown public key version " + strconv.Itoa(e.KeyVersion))
|
||||
}
|
||||
var fingerprint []byte
|
||||
if e.KeyVersion == 6 {
|
||||
fingerprint = make([]byte, fingerprintSizeV6)
|
||||
} else if e.KeyVersion == 4 {
|
||||
fingerprint = make([]byte, fingerprintSize)
|
||||
}
|
||||
_, err = readFull(r, fingerprint)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
e.KeyFingerprint = fingerprint
|
||||
if e.KeyVersion == 6 {
|
||||
e.KeyId = binary.BigEndian.Uint64(e.KeyFingerprint[:keyIdSize])
|
||||
} else if e.KeyVersion == 4 {
|
||||
e.KeyId = binary.BigEndian.Uint64(e.KeyFingerprint[fingerprintSize-keyIdSize : fingerprintSize])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_, err = readFull(r, buf[:8])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
e.KeyId = binary.BigEndian.Uint64(buf[:keyIdSize])
|
||||
}
|
||||
|
||||
_, err = readFull(r, buf[:1])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
e.Algo = PublicKeyAlgorithm(buf[0])
|
||||
var cipherFunction byte
|
||||
switch e.Algo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
||||
e.encryptedMPI1 = new(encoding.MPI)
|
||||
@@ -68,26 +123,39 @@ func (e *EncryptedKey) parse(r io.Reader) (err error) {
|
||||
if _, err = e.encryptedMPI2.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
_, err = consumeAll(r)
|
||||
case PubKeyAlgoX25519:
|
||||
e.ephemeralPublicX25519, e.encryptedSession, cipherFunction, err = x25519.DecodeFields(r, e.Version == 6)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
func checksumKeyMaterial(key []byte) uint16 {
|
||||
var checksum uint16
|
||||
for _, v := range key {
|
||||
checksum += uint16(v)
|
||||
case PubKeyAlgoX448:
|
||||
e.ephemeralPublicX448, e.encryptedSession, cipherFunction, err = x448.DecodeFields(r, e.Version == 6)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return checksum
|
||||
}
|
||||
if e.Version < 6 {
|
||||
switch e.Algo {
|
||||
case PubKeyAlgoX25519, PubKeyAlgoX448:
|
||||
e.CipherFunc = CipherFunction(cipherFunction)
|
||||
// Check for validiy is in the Decrypt method
|
||||
}
|
||||
}
|
||||
|
||||
_, err = consumeAll(r)
|
||||
return
|
||||
}
|
||||
|
||||
// Decrypt decrypts an encrypted session key with the given private key. The
|
||||
// private key must have been decrypted first.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
|
||||
if e.KeyId != 0 && e.KeyId != priv.KeyId {
|
||||
if e.Version < 6 && e.KeyId != 0 && e.KeyId != priv.KeyId {
|
||||
return errors.InvalidArgumentError("cannot decrypt encrypted session key for key id " + strconv.FormatUint(e.KeyId, 16) + " with private key id " + strconv.FormatUint(priv.KeyId, 16))
|
||||
}
|
||||
if e.Version == 6 && e.KeyVersion != 0 && !bytes.Equal(e.KeyFingerprint, priv.Fingerprint) {
|
||||
return errors.InvalidArgumentError("cannot decrypt encrypted session key for key fingerprint " + hex.EncodeToString(e.KeyFingerprint) + " with private key fingerprint " + hex.EncodeToString(priv.Fingerprint))
|
||||
}
|
||||
if e.Algo != priv.PubKeyAlgo {
|
||||
return errors.InvalidArgumentError("cannot decrypt encrypted session key of type " + strconv.Itoa(int(e.Algo)) + " with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
|
||||
}
|
||||
@@ -113,52 +181,116 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
|
||||
vsG := e.encryptedMPI1.Bytes()
|
||||
m := e.encryptedMPI2.Bytes()
|
||||
oid := priv.PublicKey.oid.EncodedBytes()
|
||||
b, err = ecdh.Decrypt(priv.PrivateKey.(*ecdh.PrivateKey), vsG, m, oid, priv.PublicKey.Fingerprint[:])
|
||||
fp := priv.PublicKey.Fingerprint[:]
|
||||
if priv.PublicKey.Version == 5 {
|
||||
// For v5 the, the fingerprint must be restricted to 20 bytes
|
||||
fp = fp[:20]
|
||||
}
|
||||
b, err = ecdh.Decrypt(priv.PrivateKey.(*ecdh.PrivateKey), vsG, m, oid, fp)
|
||||
case PubKeyAlgoX25519:
|
||||
b, err = x25519.Decrypt(priv.PrivateKey.(*x25519.PrivateKey), e.ephemeralPublicX25519, e.encryptedSession)
|
||||
case PubKeyAlgoX448:
|
||||
b, err = x448.Decrypt(priv.PrivateKey.(*x448.PrivateKey), e.ephemeralPublicX448, e.encryptedSession)
|
||||
default:
|
||||
err = errors.InvalidArgumentError("cannot decrypt encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var key []byte
|
||||
switch priv.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH:
|
||||
keyOffset := 0
|
||||
if e.Version < 6 {
|
||||
e.CipherFunc = CipherFunction(b[0])
|
||||
keyOffset = 1
|
||||
if !e.CipherFunc.IsSupported() {
|
||||
return errors.UnsupportedError("unsupported encryption function")
|
||||
}
|
||||
|
||||
e.Key = b[1 : len(b)-2]
|
||||
expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
|
||||
checksum := checksumKeyMaterial(e.Key)
|
||||
if checksum != expectedChecksum {
|
||||
return errors.StructuralError("EncryptedKey checksum incorrect")
|
||||
}
|
||||
|
||||
key, err = decodeChecksumKey(b[keyOffset:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case PubKeyAlgoX25519, PubKeyAlgoX448:
|
||||
if e.Version < 6 {
|
||||
switch e.CipherFunc {
|
||||
case CipherAES128, CipherAES192, CipherAES256:
|
||||
break
|
||||
default:
|
||||
return errors.StructuralError("v3 PKESK mandates AES as cipher function for x25519 and x448")
|
||||
}
|
||||
}
|
||||
key = b[:]
|
||||
default:
|
||||
return errors.UnsupportedError("unsupported algorithm for decryption")
|
||||
}
|
||||
e.Key = key
|
||||
return nil
|
||||
}
|
||||
|
||||
// Serialize writes the encrypted key packet, e, to w.
|
||||
func (e *EncryptedKey) Serialize(w io.Writer) error {
|
||||
var mpiLen int
|
||||
var encodedLength int
|
||||
switch e.Algo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
||||
mpiLen = int(e.encryptedMPI1.EncodedLength())
|
||||
encodedLength = int(e.encryptedMPI1.EncodedLength())
|
||||
case PubKeyAlgoElGamal:
|
||||
mpiLen = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength())
|
||||
encodedLength = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength())
|
||||
case PubKeyAlgoECDH:
|
||||
mpiLen = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength())
|
||||
encodedLength = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength())
|
||||
case PubKeyAlgoX25519:
|
||||
encodedLength = x25519.EncodedFieldsLength(e.encryptedSession, e.Version == 6)
|
||||
case PubKeyAlgoX448:
|
||||
encodedLength = x448.EncodedFieldsLength(e.encryptedSession, e.Version == 6)
|
||||
default:
|
||||
return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo)))
|
||||
}
|
||||
|
||||
err := serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen)
|
||||
packetLen := versionSize /* version */ + keyIdSize /* key id */ + algorithmSize /* algo */ + encodedLength
|
||||
if e.Version == 6 {
|
||||
packetLen = versionSize /* version */ + algorithmSize /* algo */ + encodedLength + keyVersionSize /* key version */
|
||||
if e.KeyVersion == 6 {
|
||||
packetLen += fingerprintSizeV6
|
||||
} else if e.KeyVersion == 4 {
|
||||
packetLen += fingerprintSize
|
||||
}
|
||||
}
|
||||
|
||||
err := serializeHeader(w, packetTypeEncryptedKey, packetLen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.Write([]byte{encryptedKeyVersion})
|
||||
binary.Write(w, binary.BigEndian, e.KeyId)
|
||||
w.Write([]byte{byte(e.Algo)})
|
||||
_, err = w.Write([]byte{byte(e.Version)})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if e.Version == 6 {
|
||||
_, err = w.Write([]byte{byte(e.KeyVersion)})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// The key version number may also be zero,
|
||||
// and the fingerprint omitted
|
||||
if e.KeyVersion != 0 {
|
||||
_, err = w.Write(e.KeyFingerprint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Write KeyID
|
||||
err = binary.Write(w, binary.BigEndian, e.KeyId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err = w.Write([]byte{byte(e.Algo)})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch e.Algo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
||||
@@ -176,34 +308,115 @@ func (e *EncryptedKey) Serialize(w io.Writer) error {
|
||||
}
|
||||
_, err := w.Write(e.encryptedMPI2.EncodedBytes())
|
||||
return err
|
||||
case PubKeyAlgoX25519:
|
||||
err := x25519.EncodeFields(w, e.ephemeralPublicX25519, e.encryptedSession, byte(e.CipherFunc), e.Version == 6)
|
||||
return err
|
||||
case PubKeyAlgoX448:
|
||||
err := x448.EncodeFields(w, e.ephemeralPublicX448, e.encryptedSession, byte(e.CipherFunc), e.Version == 6)
|
||||
return err
|
||||
default:
|
||||
panic("internal error")
|
||||
}
|
||||
}
|
||||
|
||||
// SerializeEncryptedKey serializes an encrypted key packet to w that contains
|
||||
// SerializeEncryptedKeyAEAD serializes an encrypted key packet to w that contains
|
||||
// key, encrypted to pub.
|
||||
// If aeadSupported is set, PKESK v6 is used, otherwise v3.
|
||||
// Note: aeadSupported MUST match the value passed to SerializeSymmetricallyEncrypted.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error {
|
||||
var buf [10]byte
|
||||
buf[0] = encryptedKeyVersion
|
||||
binary.BigEndian.PutUint64(buf[1:9], pub.KeyId)
|
||||
buf[9] = byte(pub.PubKeyAlgo)
|
||||
func SerializeEncryptedKeyAEAD(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, aeadSupported bool, key []byte, config *Config) error {
|
||||
return SerializeEncryptedKeyAEADwithHiddenOption(w, pub, cipherFunc, aeadSupported, key, false, config)
|
||||
}
|
||||
|
||||
keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */)
|
||||
// SerializeEncryptedKeyAEADwithHiddenOption serializes an encrypted key packet to w that contains
|
||||
// key, encrypted to pub.
|
||||
// Offers the hidden flag option to indicated if the PKESK packet should include a wildcard KeyID.
|
||||
// If aeadSupported is set, PKESK v6 is used, otherwise v3.
|
||||
// Note: aeadSupported MUST match the value passed to SerializeSymmetricallyEncrypted.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func SerializeEncryptedKeyAEADwithHiddenOption(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, aeadSupported bool, key []byte, hidden bool, config *Config) error {
|
||||
var buf [36]byte // max possible header size is v6
|
||||
lenHeaderWritten := versionSize
|
||||
version := 3
|
||||
|
||||
if aeadSupported {
|
||||
version = 6
|
||||
}
|
||||
// An implementation MUST NOT generate ElGamal v6 PKESKs.
|
||||
if version == 6 && pub.PubKeyAlgo == PubKeyAlgoElGamal {
|
||||
return errors.InvalidArgumentError("ElGamal v6 PKESK are not allowed")
|
||||
}
|
||||
// In v3 PKESKs, for x25519 and x448, mandate using AES
|
||||
if version == 3 && (pub.PubKeyAlgo == PubKeyAlgoX25519 || pub.PubKeyAlgo == PubKeyAlgoX448) {
|
||||
switch cipherFunc {
|
||||
case CipherAES128, CipherAES192, CipherAES256:
|
||||
break
|
||||
default:
|
||||
return errors.InvalidArgumentError("v3 PKESK mandates AES for x25519 and x448")
|
||||
}
|
||||
}
|
||||
|
||||
buf[0] = byte(version)
|
||||
|
||||
// If hidden is set, the key should be hidden
|
||||
// An implementation MAY accept or use a Key ID of all zeros,
|
||||
// or a key version of zero and no key fingerprint, to hide the intended decryption key.
|
||||
// See Section 5.1.8. in the open pgp crypto refresh
|
||||
if version == 6 {
|
||||
if !hidden {
|
||||
// A one-octet size of the following two fields.
|
||||
buf[1] = byte(keyVersionSize + len(pub.Fingerprint))
|
||||
// A one octet key version number.
|
||||
buf[2] = byte(pub.Version)
|
||||
lenHeaderWritten += keyVersionSize + 1
|
||||
// The fingerprint of the public key
|
||||
copy(buf[lenHeaderWritten:lenHeaderWritten+len(pub.Fingerprint)], pub.Fingerprint)
|
||||
lenHeaderWritten += len(pub.Fingerprint)
|
||||
} else {
|
||||
// The size may also be zero, and the key version
|
||||
// and fingerprint omitted for an "anonymous recipient"
|
||||
buf[1] = 0
|
||||
lenHeaderWritten += 1
|
||||
}
|
||||
} else {
|
||||
if !hidden {
|
||||
binary.BigEndian.PutUint64(buf[versionSize:(versionSize+keyIdSize)], pub.KeyId)
|
||||
}
|
||||
lenHeaderWritten += keyIdSize
|
||||
}
|
||||
buf[lenHeaderWritten] = byte(pub.PubKeyAlgo)
|
||||
lenHeaderWritten += algorithmSize
|
||||
|
||||
var keyBlock []byte
|
||||
switch pub.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH:
|
||||
lenKeyBlock := len(key) + 2
|
||||
if version < 6 {
|
||||
lenKeyBlock += 1 // cipher type included
|
||||
}
|
||||
keyBlock = make([]byte, lenKeyBlock)
|
||||
keyOffset := 0
|
||||
if version < 6 {
|
||||
keyBlock[0] = byte(cipherFunc)
|
||||
copy(keyBlock[1:], key)
|
||||
checksum := checksumKeyMaterial(key)
|
||||
keyBlock[1+len(key)] = byte(checksum >> 8)
|
||||
keyBlock[1+len(key)+1] = byte(checksum)
|
||||
keyOffset = 1
|
||||
}
|
||||
encodeChecksumKey(keyBlock[keyOffset:], key)
|
||||
case PubKeyAlgoX25519, PubKeyAlgoX448:
|
||||
// algorithm is added in plaintext below
|
||||
keyBlock = key
|
||||
}
|
||||
|
||||
switch pub.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
||||
return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
|
||||
return serializeEncryptedKeyRSA(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*rsa.PublicKey), keyBlock)
|
||||
case PubKeyAlgoElGamal:
|
||||
return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
|
||||
return serializeEncryptedKeyElGamal(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*elgamal.PublicKey), keyBlock)
|
||||
case PubKeyAlgoECDH:
|
||||
return serializeEncryptedKeyECDH(w, config.Random(), buf, pub.PublicKey.(*ecdh.PublicKey), keyBlock, pub.oid, pub.Fingerprint)
|
||||
return serializeEncryptedKeyECDH(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*ecdh.PublicKey), keyBlock, pub.oid, pub.Fingerprint)
|
||||
case PubKeyAlgoX25519:
|
||||
return serializeEncryptedKeyX25519(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*x25519.PublicKey), keyBlock, byte(cipherFunc), version)
|
||||
case PubKeyAlgoX448:
|
||||
return serializeEncryptedKeyX448(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*x448.PublicKey), keyBlock, byte(cipherFunc), version)
|
||||
case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
|
||||
return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
|
||||
}
|
||||
@@ -211,14 +424,32 @@ func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunctio
|
||||
return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
|
||||
}
|
||||
|
||||
func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error {
|
||||
// SerializeEncryptedKey serializes an encrypted key packet to w that contains
|
||||
// key, encrypted to pub.
|
||||
// PKESKv6 is used if config.AEAD() is not nil.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
// Deprecated: Use SerializeEncryptedKeyAEAD instead.
|
||||
func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error {
|
||||
return SerializeEncryptedKeyAEAD(w, pub, cipherFunc, config.AEAD() != nil, key, config)
|
||||
}
|
||||
|
||||
// SerializeEncryptedKeyWithHiddenOption serializes an encrypted key packet to w that contains
|
||||
// key, encrypted to pub. PKESKv6 is used if config.AEAD() is not nil.
|
||||
// The hidden option controls if the packet should be anonymous, i.e., omit key metadata.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
// Deprecated: Use SerializeEncryptedKeyAEADwithHiddenOption instead.
|
||||
func SerializeEncryptedKeyWithHiddenOption(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, hidden bool, config *Config) error {
|
||||
return SerializeEncryptedKeyAEADwithHiddenOption(w, pub, cipherFunc, config.AEAD() != nil, key, hidden, config)
|
||||
}
|
||||
|
||||
func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header []byte, pub *rsa.PublicKey, keyBlock []byte) error {
|
||||
cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
|
||||
if err != nil {
|
||||
return errors.InvalidArgumentError("RSA encryption failed: " + err.Error())
|
||||
}
|
||||
|
||||
cipherMPI := encoding.NewMPI(cipherText)
|
||||
packetLen := 10 /* header length */ + int(cipherMPI.EncodedLength())
|
||||
packetLen := len(header) /* header length */ + int(cipherMPI.EncodedLength())
|
||||
|
||||
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
|
||||
if err != nil {
|
||||
@@ -232,13 +463,13 @@ func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error {
|
||||
func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header []byte, pub *elgamal.PublicKey, keyBlock []byte) error {
|
||||
c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
|
||||
if err != nil {
|
||||
return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error())
|
||||
}
|
||||
|
||||
packetLen := 10 /* header length */
|
||||
packetLen := len(header) /* header length */
|
||||
packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
|
||||
packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
|
||||
|
||||
@@ -257,7 +488,7 @@ func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte,
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeEncryptedKeyECDH(w io.Writer, rand io.Reader, header [10]byte, pub *ecdh.PublicKey, keyBlock []byte, oid encoding.Field, fingerprint []byte) error {
|
||||
func serializeEncryptedKeyECDH(w io.Writer, rand io.Reader, header []byte, pub *ecdh.PublicKey, keyBlock []byte, oid encoding.Field, fingerprint []byte) error {
|
||||
vsG, c, err := ecdh.Encrypt(rand, pub, keyBlock, oid.EncodedBytes(), fingerprint)
|
||||
if err != nil {
|
||||
return errors.InvalidArgumentError("ECDH encryption failed: " + err.Error())
|
||||
@@ -266,7 +497,7 @@ func serializeEncryptedKeyECDH(w io.Writer, rand io.Reader, header [10]byte, pub
|
||||
g := encoding.NewMPI(vsG)
|
||||
m := encoding.NewOID(c)
|
||||
|
||||
packetLen := 10 /* header length */
|
||||
packetLen := len(header) /* header length */
|
||||
packetLen += int(g.EncodedLength()) + int(m.EncodedLength())
|
||||
|
||||
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
|
||||
@@ -284,3 +515,70 @@ func serializeEncryptedKeyECDH(w io.Writer, rand io.Reader, header [10]byte, pub
|
||||
_, err = w.Write(m.EncodedBytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeEncryptedKeyX25519(w io.Writer, rand io.Reader, header []byte, pub *x25519.PublicKey, keyBlock []byte, cipherFunc byte, version int) error {
|
||||
ephemeralPublicX25519, ciphertext, err := x25519.Encrypt(rand, pub, keyBlock)
|
||||
if err != nil {
|
||||
return errors.InvalidArgumentError("x25519 encryption failed: " + err.Error())
|
||||
}
|
||||
|
||||
packetLen := len(header) /* header length */
|
||||
packetLen += x25519.EncodedFieldsLength(ciphertext, version == 6)
|
||||
|
||||
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = w.Write(header[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return x25519.EncodeFields(w, ephemeralPublicX25519, ciphertext, cipherFunc, version == 6)
|
||||
}
|
||||
|
||||
func serializeEncryptedKeyX448(w io.Writer, rand io.Reader, header []byte, pub *x448.PublicKey, keyBlock []byte, cipherFunc byte, version int) error {
|
||||
ephemeralPublicX448, ciphertext, err := x448.Encrypt(rand, pub, keyBlock)
|
||||
if err != nil {
|
||||
return errors.InvalidArgumentError("x448 encryption failed: " + err.Error())
|
||||
}
|
||||
|
||||
packetLen := len(header) /* header length */
|
||||
packetLen += x448.EncodedFieldsLength(ciphertext, version == 6)
|
||||
|
||||
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = w.Write(header[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return x448.EncodeFields(w, ephemeralPublicX448, ciphertext, cipherFunc, version == 6)
|
||||
}
|
||||
|
||||
func checksumKeyMaterial(key []byte) uint16 {
|
||||
var checksum uint16
|
||||
for _, v := range key {
|
||||
checksum += uint16(v)
|
||||
}
|
||||
return checksum
|
||||
}
|
||||
|
||||
func decodeChecksumKey(msg []byte) (key []byte, err error) {
|
||||
key = msg[:len(msg)-2]
|
||||
expectedChecksum := uint16(msg[len(msg)-2])<<8 | uint16(msg[len(msg)-1])
|
||||
checksum := checksumKeyMaterial(key)
|
||||
if checksum != expectedChecksum {
|
||||
err = errors.StructuralError("session key checksum is incorrect")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func encodeChecksumKey(buffer []byte, key []byte) {
|
||||
copy(buffer, key)
|
||||
checksum := checksumKeyMaterial(key)
|
||||
buffer[len(key)] = byte(checksum >> 8)
|
||||
buffer[len(key)+1] = byte(checksum)
|
||||
}
|
||||
|
||||
4
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go
generated
vendored
4
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go
generated
vendored
@@ -58,9 +58,9 @@ func (l *LiteralData) parse(r io.Reader) (err error) {
|
||||
// on completion. The fileName is truncated to 255 bytes.
|
||||
func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) {
|
||||
var buf [4]byte
|
||||
buf[0] = 't'
|
||||
if isBinary {
|
||||
buf[0] = 'b'
|
||||
if !isBinary {
|
||||
buf[0] = 'u'
|
||||
}
|
||||
if len(fileName) > 255 {
|
||||
fileName = fileName[:255]
|
||||
|
||||
33
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/marker.go
generated
vendored
Normal file
33
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/marker.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package packet
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
type Marker struct{}
|
||||
|
||||
const markerString = "PGP"
|
||||
|
||||
// parse just checks if the packet contains "PGP".
|
||||
func (m *Marker) parse(reader io.Reader) error {
|
||||
var buffer [3]byte
|
||||
if _, err := io.ReadFull(reader, buffer[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if string(buffer[:]) != markerString {
|
||||
return errors.StructuralError("invalid marker packet")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SerializeMarker writes a marker packet to writer.
|
||||
func SerializeMarker(writer io.Writer) error {
|
||||
err := serializeHeader(writer, packetTypeMarker, len(markerString))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = writer.Write([]byte(markerString))
|
||||
return err
|
||||
}
|
||||
120
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go
generated
vendored
120
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go
generated
vendored
@@ -7,34 +7,37 @@ package packet
|
||||
import (
|
||||
"crypto"
|
||||
"encoding/binary"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
)
|
||||
|
||||
// OnePassSignature represents a one-pass signature packet. See RFC 4880,
|
||||
// section 5.4.
|
||||
type OnePassSignature struct {
|
||||
Version int
|
||||
SigType SignatureType
|
||||
Hash crypto.Hash
|
||||
PubKeyAlgo PublicKeyAlgorithm
|
||||
KeyId uint64
|
||||
IsLast bool
|
||||
Salt []byte // v6 only
|
||||
KeyFingerprint []byte // v6 only
|
||||
}
|
||||
|
||||
const onePassSignatureVersion = 3
|
||||
|
||||
func (ops *OnePassSignature) parse(r io.Reader) (err error) {
|
||||
var buf [13]byte
|
||||
|
||||
_, err = readFull(r, buf[:])
|
||||
var buf [8]byte
|
||||
// Read: version | signature type | hash algorithm | public-key algorithm
|
||||
_, err = readFull(r, buf[:4])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if buf[0] != onePassSignatureVersion {
|
||||
err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
|
||||
if buf[0] != 3 && buf[0] != 6 {
|
||||
return errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
|
||||
}
|
||||
ops.Version = int(buf[0])
|
||||
|
||||
var ok bool
|
||||
ops.Hash, ok = algorithm.HashIdToHashWithSha1(buf[2])
|
||||
@@ -44,15 +47,69 @@ func (ops *OnePassSignature) parse(r io.Reader) (err error) {
|
||||
|
||||
ops.SigType = SignatureType(buf[1])
|
||||
ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3])
|
||||
ops.KeyId = binary.BigEndian.Uint64(buf[4:12])
|
||||
ops.IsLast = buf[12] != 0
|
||||
|
||||
if ops.Version == 6 {
|
||||
// Only for v6, a variable-length field containing the salt
|
||||
_, err = readFull(r, buf[:1])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
saltLength := int(buf[0])
|
||||
var expectedSaltLength int
|
||||
expectedSaltLength, err = SaltLengthForHash(ops.Hash)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if saltLength != expectedSaltLength {
|
||||
err = errors.StructuralError("unexpected salt size for the given hash algorithm")
|
||||
return
|
||||
}
|
||||
salt := make([]byte, expectedSaltLength)
|
||||
_, err = readFull(r, salt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ops.Salt = salt
|
||||
|
||||
// Only for v6 packets, 32 octets of the fingerprint of the signing key.
|
||||
fingerprint := make([]byte, 32)
|
||||
_, err = readFull(r, fingerprint)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ops.KeyFingerprint = fingerprint
|
||||
ops.KeyId = binary.BigEndian.Uint64(ops.KeyFingerprint[:8])
|
||||
} else {
|
||||
_, err = readFull(r, buf[:8])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ops.KeyId = binary.BigEndian.Uint64(buf[:8])
|
||||
}
|
||||
|
||||
_, err = readFull(r, buf[:1])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ops.IsLast = buf[0] != 0
|
||||
return
|
||||
}
|
||||
|
||||
// Serialize marshals the given OnePassSignature to w.
|
||||
func (ops *OnePassSignature) Serialize(w io.Writer) error {
|
||||
var buf [13]byte
|
||||
buf[0] = onePassSignatureVersion
|
||||
//v3 length 1+1+1+1+8+1 =
|
||||
packetLength := 13
|
||||
if ops.Version == 6 {
|
||||
// v6 length 1+1+1+1+1+len(salt)+32+1 =
|
||||
packetLength = 38 + len(ops.Salt)
|
||||
}
|
||||
|
||||
if err := serializeHeader(w, packetTypeOnePassSignature, packetLength); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var buf [8]byte
|
||||
buf[0] = byte(ops.Version)
|
||||
buf[1] = uint8(ops.SigType)
|
||||
var ok bool
|
||||
buf[2], ok = algorithm.HashToHashIdWithSha1(ops.Hash)
|
||||
@@ -60,14 +117,41 @@ func (ops *OnePassSignature) Serialize(w io.Writer) error {
|
||||
return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash)))
|
||||
}
|
||||
buf[3] = uint8(ops.PubKeyAlgo)
|
||||
binary.BigEndian.PutUint64(buf[4:12], ops.KeyId)
|
||||
if ops.IsLast {
|
||||
buf[12] = 1
|
||||
|
||||
_, err := w.Write(buf[:4])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil {
|
||||
if ops.Version == 6 {
|
||||
// write salt for v6 signatures
|
||||
_, err := w.Write([]byte{uint8(len(ops.Salt))})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := w.Write(buf[:])
|
||||
_, err = w.Write(ops.Salt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// write fingerprint v6 signatures
|
||||
_, err = w.Write(ops.KeyFingerprint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
binary.BigEndian.PutUint64(buf[:8], ops.KeyId)
|
||||
_, err := w.Write(buf[:8])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
isLast := []byte{byte(0)}
|
||||
if ops.IsLast {
|
||||
isLast[0] = 1
|
||||
}
|
||||
|
||||
_, err = w.Write(isLast)
|
||||
return err
|
||||
}
|
||||
|
||||
3
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go
generated
vendored
3
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go
generated
vendored
@@ -7,7 +7,6 @@ package packet
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
@@ -26,7 +25,7 @@ type OpaquePacket struct {
|
||||
}
|
||||
|
||||
func (op *OpaquePacket) parse(r io.Reader) (err error) {
|
||||
op.Contents, err = ioutil.ReadAll(r)
|
||||
op.Contents, err = io.ReadAll(r)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
154
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go
generated
vendored
154
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go
generated
vendored
@@ -311,12 +311,15 @@ const (
|
||||
packetTypePrivateSubkey packetType = 7
|
||||
packetTypeCompressed packetType = 8
|
||||
packetTypeSymmetricallyEncrypted packetType = 9
|
||||
packetTypeMarker packetType = 10
|
||||
packetTypeLiteralData packetType = 11
|
||||
packetTypeTrust packetType = 12
|
||||
packetTypeUserId packetType = 13
|
||||
packetTypePublicSubkey packetType = 14
|
||||
packetTypeUserAttribute packetType = 17
|
||||
packetTypeSymmetricallyEncryptedIntegrityProtected packetType = 18
|
||||
packetTypeAEADEncrypted packetType = 20
|
||||
packetPadding packetType = 21
|
||||
)
|
||||
|
||||
// EncryptedDataPacket holds encrypted data. It is currently implemented by
|
||||
@@ -328,7 +331,7 @@ type EncryptedDataPacket interface {
|
||||
// Read reads a single OpenPGP packet from the given io.Reader. If there is an
|
||||
// error parsing a packet, the whole packet is consumed from the input.
|
||||
func Read(r io.Reader) (p Packet, err error) {
|
||||
tag, _, contents, err := readHeader(r)
|
||||
tag, len, contents, err := readHeader(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -367,8 +370,93 @@ func Read(r io.Reader) (p Packet, err error) {
|
||||
p = se
|
||||
case packetTypeAEADEncrypted:
|
||||
p = new(AEADEncrypted)
|
||||
default:
|
||||
case packetPadding:
|
||||
p = Padding(len)
|
||||
case packetTypeMarker:
|
||||
p = new(Marker)
|
||||
case packetTypeTrust:
|
||||
// Not implemented, just consume
|
||||
err = errors.UnknownPacketTypeError(tag)
|
||||
default:
|
||||
// Packet Tags from 0 to 39 are critical.
|
||||
// Packet Tags from 40 to 63 are non-critical.
|
||||
if tag < 40 {
|
||||
err = errors.CriticalUnknownPacketTypeError(tag)
|
||||
} else {
|
||||
err = errors.UnknownPacketTypeError(tag)
|
||||
}
|
||||
}
|
||||
if p != nil {
|
||||
err = p.parse(contents)
|
||||
}
|
||||
if err != nil {
|
||||
consumeAll(contents)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ReadWithCheck reads a single OpenPGP message packet from the given io.Reader. If there is an
|
||||
// error parsing a packet, the whole packet is consumed from the input.
|
||||
// ReadWithCheck additionally checks if the OpenPGP message packet sequence adheres
|
||||
// to the packet composition rules in rfc4880, if not throws an error.
|
||||
func ReadWithCheck(r io.Reader, sequence *SequenceVerifier) (p Packet, msgErr error, err error) {
|
||||
tag, len, contents, err := readHeader(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch tag {
|
||||
case packetTypeEncryptedKey:
|
||||
msgErr = sequence.Next(ESKSymbol)
|
||||
p = new(EncryptedKey)
|
||||
case packetTypeSignature:
|
||||
msgErr = sequence.Next(SigSymbol)
|
||||
p = new(Signature)
|
||||
case packetTypeSymmetricKeyEncrypted:
|
||||
msgErr = sequence.Next(ESKSymbol)
|
||||
p = new(SymmetricKeyEncrypted)
|
||||
case packetTypeOnePassSignature:
|
||||
msgErr = sequence.Next(OPSSymbol)
|
||||
p = new(OnePassSignature)
|
||||
case packetTypeCompressed:
|
||||
msgErr = sequence.Next(CompSymbol)
|
||||
p = new(Compressed)
|
||||
case packetTypeSymmetricallyEncrypted:
|
||||
msgErr = sequence.Next(EncSymbol)
|
||||
p = new(SymmetricallyEncrypted)
|
||||
case packetTypeLiteralData:
|
||||
msgErr = sequence.Next(LDSymbol)
|
||||
p = new(LiteralData)
|
||||
case packetTypeSymmetricallyEncryptedIntegrityProtected:
|
||||
msgErr = sequence.Next(EncSymbol)
|
||||
se := new(SymmetricallyEncrypted)
|
||||
se.IntegrityProtected = true
|
||||
p = se
|
||||
case packetTypeAEADEncrypted:
|
||||
msgErr = sequence.Next(EncSymbol)
|
||||
p = new(AEADEncrypted)
|
||||
case packetPadding:
|
||||
p = Padding(len)
|
||||
case packetTypeMarker:
|
||||
p = new(Marker)
|
||||
case packetTypeTrust:
|
||||
// Not implemented, just consume
|
||||
err = errors.UnknownPacketTypeError(tag)
|
||||
case packetTypePrivateKey,
|
||||
packetTypePrivateSubkey,
|
||||
packetTypePublicKey,
|
||||
packetTypePublicSubkey,
|
||||
packetTypeUserId,
|
||||
packetTypeUserAttribute:
|
||||
msgErr = sequence.Next(UnknownSymbol)
|
||||
consumeAll(contents)
|
||||
default:
|
||||
// Packet Tags from 0 to 39 are critical.
|
||||
// Packet Tags from 40 to 63 are non-critical.
|
||||
if tag < 40 {
|
||||
err = errors.CriticalUnknownPacketTypeError(tag)
|
||||
} else {
|
||||
err = errors.UnknownPacketTypeError(tag)
|
||||
}
|
||||
}
|
||||
if p != nil {
|
||||
err = p.parse(contents)
|
||||
@@ -385,17 +473,17 @@ type SignatureType uint8
|
||||
|
||||
const (
|
||||
SigTypeBinary SignatureType = 0x00
|
||||
SigTypeText = 0x01
|
||||
SigTypeGenericCert = 0x10
|
||||
SigTypePersonaCert = 0x11
|
||||
SigTypeCasualCert = 0x12
|
||||
SigTypePositiveCert = 0x13
|
||||
SigTypeSubkeyBinding = 0x18
|
||||
SigTypePrimaryKeyBinding = 0x19
|
||||
SigTypeDirectSignature = 0x1F
|
||||
SigTypeKeyRevocation = 0x20
|
||||
SigTypeSubkeyRevocation = 0x28
|
||||
SigTypeCertificationRevocation = 0x30
|
||||
SigTypeText SignatureType = 0x01
|
||||
SigTypeGenericCert SignatureType = 0x10
|
||||
SigTypePersonaCert SignatureType = 0x11
|
||||
SigTypeCasualCert SignatureType = 0x12
|
||||
SigTypePositiveCert SignatureType = 0x13
|
||||
SigTypeSubkeyBinding SignatureType = 0x18
|
||||
SigTypePrimaryKeyBinding SignatureType = 0x19
|
||||
SigTypeDirectSignature SignatureType = 0x1F
|
||||
SigTypeKeyRevocation SignatureType = 0x20
|
||||
SigTypeSubkeyRevocation SignatureType = 0x28
|
||||
SigTypeCertificationRevocation SignatureType = 0x30
|
||||
)
|
||||
|
||||
// PublicKeyAlgorithm represents the different public key system specified for
|
||||
@@ -412,6 +500,11 @@ const (
|
||||
PubKeyAlgoECDSA PublicKeyAlgorithm = 19
|
||||
// https://www.ietf.org/archive/id/draft-koch-eddsa-for-openpgp-04.txt
|
||||
PubKeyAlgoEdDSA PublicKeyAlgorithm = 22
|
||||
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh
|
||||
PubKeyAlgoX25519 PublicKeyAlgorithm = 25
|
||||
PubKeyAlgoX448 PublicKeyAlgorithm = 26
|
||||
PubKeyAlgoEd25519 PublicKeyAlgorithm = 27
|
||||
PubKeyAlgoEd448 PublicKeyAlgorithm = 28
|
||||
|
||||
// Deprecated in RFC 4880, Section 13.5. Use key flags instead.
|
||||
PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
|
||||
@@ -422,7 +515,7 @@ const (
|
||||
// key of the given type.
|
||||
func (pka PublicKeyAlgorithm) CanEncrypt() bool {
|
||||
switch pka {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH:
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH, PubKeyAlgoX25519, PubKeyAlgoX448:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -432,7 +525,7 @@ func (pka PublicKeyAlgorithm) CanEncrypt() bool {
|
||||
// sign a message.
|
||||
func (pka PublicKeyAlgorithm) CanSign() bool {
|
||||
switch pka {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA:
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA, PubKeyAlgoEd25519, PubKeyAlgoEd448:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -512,6 +605,11 @@ func (mode AEADMode) TagLength() int {
|
||||
return algorithm.AEADMode(mode).TagLength()
|
||||
}
|
||||
|
||||
// IsSupported returns true if the aead mode is supported from the library
|
||||
func (mode AEADMode) IsSupported() bool {
|
||||
return algorithm.AEADMode(mode).TagLength() > 0
|
||||
}
|
||||
|
||||
// new returns a fresh instance of the given mode.
|
||||
func (mode AEADMode) new(block cipher.Block) cipher.AEAD {
|
||||
return algorithm.AEADMode(mode).New(block)
|
||||
@@ -526,8 +624,17 @@ const (
|
||||
KeySuperseded ReasonForRevocation = 1
|
||||
KeyCompromised ReasonForRevocation = 2
|
||||
KeyRetired ReasonForRevocation = 3
|
||||
UserIDNotValid ReasonForRevocation = 32
|
||||
Unknown ReasonForRevocation = 200
|
||||
)
|
||||
|
||||
func NewReasonForRevocation(value byte) ReasonForRevocation {
|
||||
if value < 4 || value == 32 {
|
||||
return ReasonForRevocation(value)
|
||||
}
|
||||
return Unknown
|
||||
}
|
||||
|
||||
// Curve is a mapping to supported ECC curves for key generation.
|
||||
// See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-06.html#name-curve-specific-wire-formats
|
||||
type Curve string
|
||||
@@ -549,3 +656,20 @@ type TrustLevel uint8
|
||||
|
||||
// TrustAmount represents a trust amount per RFC4880 5.2.3.13
|
||||
type TrustAmount uint8
|
||||
|
||||
const (
|
||||
// versionSize is the length in bytes of the version value.
|
||||
versionSize = 1
|
||||
// algorithmSize is the length in bytes of the key algorithm value.
|
||||
algorithmSize = 1
|
||||
// keyVersionSize is the length in bytes of the key version value
|
||||
keyVersionSize = 1
|
||||
// keyIdSize is the length in bytes of the key identifier value.
|
||||
keyIdSize = 8
|
||||
// timestampSize is the length in bytes of encoded timestamps.
|
||||
timestampSize = 4
|
||||
// fingerprintSizeV6 is the length in bytes of the key fingerprint in v6.
|
||||
fingerprintSizeV6 = 32
|
||||
// fingerprintSize is the length in bytes of the key fingerprint.
|
||||
fingerprintSize = 20
|
||||
)
|
||||
|
||||
222
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_sequence.go
generated
vendored
Normal file
222
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_sequence.go
generated
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
package packet
|
||||
|
||||
// This file implements the pushdown automata (PDA) from PGPainless (Paul Schaub)
|
||||
// to verify pgp packet sequences. See Paul's blogpost for more details:
|
||||
// https://blog.jabberhead.tk/2022/10/26/implementing-packet-sequence-validation-using-pushdown-automata/
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
func NewErrMalformedMessage(from State, input InputSymbol, stackSymbol StackSymbol) errors.ErrMalformedMessage {
|
||||
return errors.ErrMalformedMessage(fmt.Sprintf("state %d, input symbol %d, stack symbol %d ", from, input, stackSymbol))
|
||||
}
|
||||
|
||||
// InputSymbol defines the input alphabet of the PDA
|
||||
type InputSymbol uint8
|
||||
|
||||
const (
|
||||
LDSymbol InputSymbol = iota
|
||||
SigSymbol
|
||||
OPSSymbol
|
||||
CompSymbol
|
||||
ESKSymbol
|
||||
EncSymbol
|
||||
EOSSymbol
|
||||
UnknownSymbol
|
||||
)
|
||||
|
||||
// StackSymbol defines the stack alphabet of the PDA
|
||||
type StackSymbol int8
|
||||
|
||||
const (
|
||||
MsgStackSymbol StackSymbol = iota
|
||||
OpsStackSymbol
|
||||
KeyStackSymbol
|
||||
EndStackSymbol
|
||||
EmptyStackSymbol
|
||||
)
|
||||
|
||||
// State defines the states of the PDA
|
||||
type State int8
|
||||
|
||||
const (
|
||||
OpenPGPMessage State = iota
|
||||
ESKMessage
|
||||
LiteralMessage
|
||||
CompressedMessage
|
||||
EncryptedMessage
|
||||
ValidMessage
|
||||
)
|
||||
|
||||
// transition represents a state transition in the PDA
|
||||
type transition func(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error)
|
||||
|
||||
// SequenceVerifier is a pushdown automata to verify
|
||||
// PGP messages packet sequences according to rfc4880.
|
||||
type SequenceVerifier struct {
|
||||
stack []StackSymbol
|
||||
state State
|
||||
}
|
||||
|
||||
// Next performs a state transition with the given input symbol.
|
||||
// If the transition fails a ErrMalformedMessage is returned.
|
||||
func (sv *SequenceVerifier) Next(input InputSymbol) error {
|
||||
for {
|
||||
stackSymbol := sv.popStack()
|
||||
transitionFunc := getTransition(sv.state)
|
||||
nextState, newStackSymbols, redo, err := transitionFunc(input, stackSymbol)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if redo {
|
||||
sv.pushStack(stackSymbol)
|
||||
}
|
||||
for _, newStackSymbol := range newStackSymbols {
|
||||
sv.pushStack(newStackSymbol)
|
||||
}
|
||||
sv.state = nextState
|
||||
if !redo {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Valid returns true if RDA is in a valid state.
|
||||
func (sv *SequenceVerifier) Valid() bool {
|
||||
return sv.state == ValidMessage && len(sv.stack) == 0
|
||||
}
|
||||
|
||||
func (sv *SequenceVerifier) AssertValid() error {
|
||||
if !sv.Valid() {
|
||||
return errors.ErrMalformedMessage("invalid message")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewSequenceVerifier() *SequenceVerifier {
|
||||
return &SequenceVerifier{
|
||||
stack: []StackSymbol{EndStackSymbol, MsgStackSymbol},
|
||||
state: OpenPGPMessage,
|
||||
}
|
||||
}
|
||||
|
||||
func (sv *SequenceVerifier) popStack() StackSymbol {
|
||||
if len(sv.stack) == 0 {
|
||||
return EmptyStackSymbol
|
||||
}
|
||||
elemIndex := len(sv.stack) - 1
|
||||
stackSymbol := sv.stack[elemIndex]
|
||||
sv.stack = sv.stack[:elemIndex]
|
||||
return stackSymbol
|
||||
}
|
||||
|
||||
func (sv *SequenceVerifier) pushStack(stackSymbol StackSymbol) {
|
||||
sv.stack = append(sv.stack, stackSymbol)
|
||||
}
|
||||
|
||||
func getTransition(from State) transition {
|
||||
switch from {
|
||||
case OpenPGPMessage:
|
||||
return fromOpenPGPMessage
|
||||
case LiteralMessage:
|
||||
return fromLiteralMessage
|
||||
case CompressedMessage:
|
||||
return fromCompressedMessage
|
||||
case EncryptedMessage:
|
||||
return fromEncryptedMessage
|
||||
case ESKMessage:
|
||||
return fromESKMessage
|
||||
case ValidMessage:
|
||||
return fromValidMessage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// fromOpenPGPMessage is the transition for the state OpenPGPMessage.
|
||||
func fromOpenPGPMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
|
||||
if stackSymbol != MsgStackSymbol {
|
||||
return 0, nil, false, NewErrMalformedMessage(OpenPGPMessage, input, stackSymbol)
|
||||
}
|
||||
switch input {
|
||||
case LDSymbol:
|
||||
return LiteralMessage, nil, false, nil
|
||||
case SigSymbol:
|
||||
return OpenPGPMessage, []StackSymbol{MsgStackSymbol}, false, nil
|
||||
case OPSSymbol:
|
||||
return OpenPGPMessage, []StackSymbol{OpsStackSymbol, MsgStackSymbol}, false, nil
|
||||
case CompSymbol:
|
||||
return CompressedMessage, nil, false, nil
|
||||
case ESKSymbol:
|
||||
return ESKMessage, []StackSymbol{KeyStackSymbol}, false, nil
|
||||
case EncSymbol:
|
||||
return EncryptedMessage, nil, false, nil
|
||||
}
|
||||
return 0, nil, false, NewErrMalformedMessage(OpenPGPMessage, input, stackSymbol)
|
||||
}
|
||||
|
||||
// fromESKMessage is the transition for the state ESKMessage.
|
||||
func fromESKMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
|
||||
if stackSymbol != KeyStackSymbol {
|
||||
return 0, nil, false, NewErrMalformedMessage(ESKMessage, input, stackSymbol)
|
||||
}
|
||||
switch input {
|
||||
case ESKSymbol:
|
||||
return ESKMessage, []StackSymbol{KeyStackSymbol}, false, nil
|
||||
case EncSymbol:
|
||||
return EncryptedMessage, nil, false, nil
|
||||
}
|
||||
return 0, nil, false, NewErrMalformedMessage(ESKMessage, input, stackSymbol)
|
||||
}
|
||||
|
||||
// fromLiteralMessage is the transition for the state LiteralMessage.
|
||||
func fromLiteralMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
|
||||
switch input {
|
||||
case SigSymbol:
|
||||
if stackSymbol == OpsStackSymbol {
|
||||
return LiteralMessage, nil, false, nil
|
||||
}
|
||||
case EOSSymbol:
|
||||
if stackSymbol == EndStackSymbol {
|
||||
return ValidMessage, nil, false, nil
|
||||
}
|
||||
}
|
||||
return 0, nil, false, NewErrMalformedMessage(LiteralMessage, input, stackSymbol)
|
||||
}
|
||||
|
||||
// fromLiteralMessage is the transition for the state CompressedMessage.
|
||||
func fromCompressedMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
|
||||
switch input {
|
||||
case SigSymbol:
|
||||
if stackSymbol == OpsStackSymbol {
|
||||
return CompressedMessage, nil, false, nil
|
||||
}
|
||||
case EOSSymbol:
|
||||
if stackSymbol == EndStackSymbol {
|
||||
return ValidMessage, nil, false, nil
|
||||
}
|
||||
}
|
||||
return OpenPGPMessage, []StackSymbol{MsgStackSymbol}, true, nil
|
||||
}
|
||||
|
||||
// fromEncryptedMessage is the transition for the state EncryptedMessage.
|
||||
func fromEncryptedMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
|
||||
switch input {
|
||||
case SigSymbol:
|
||||
if stackSymbol == OpsStackSymbol {
|
||||
return EncryptedMessage, nil, false, nil
|
||||
}
|
||||
case EOSSymbol:
|
||||
if stackSymbol == EndStackSymbol {
|
||||
return ValidMessage, nil, false, nil
|
||||
}
|
||||
}
|
||||
return OpenPGPMessage, []StackSymbol{MsgStackSymbol}, true, nil
|
||||
}
|
||||
|
||||
// fromValidMessage is the transition for the state ValidMessage.
|
||||
func fromValidMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
|
||||
return 0, nil, false, NewErrMalformedMessage(ValidMessage, input, stackSymbol)
|
||||
}
|
||||
24
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_unsupported.go
generated
vendored
Normal file
24
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_unsupported.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
package packet
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
// UnsupportedPackage represents a OpenPGP packet with a known packet type
|
||||
// but with unsupported content.
|
||||
type UnsupportedPacket struct {
|
||||
IncompletePacket Packet
|
||||
Error errors.UnsupportedError
|
||||
}
|
||||
|
||||
// Implements the Packet interface
|
||||
func (up *UnsupportedPacket) parse(read io.Reader) error {
|
||||
err := up.IncompletePacket.parse(read)
|
||||
if castedErr, ok := err.(errors.UnsupportedError); ok {
|
||||
up.Error = castedErr
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
26
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/padding.go
generated
vendored
Normal file
26
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/padding.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
package packet
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// Padding type represents a Padding Packet (Tag 21).
|
||||
// The padding type is represented by the length of its padding.
|
||||
// see https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh#name-padding-packet-tag-21
|
||||
type Padding int
|
||||
|
||||
// parse just ignores the padding content.
|
||||
func (pad Padding) parse(reader io.Reader) error {
|
||||
_, err := io.CopyN(io.Discard, reader, int64(pad))
|
||||
return err
|
||||
}
|
||||
|
||||
// SerializePadding writes the padding to writer.
|
||||
func (pad Padding) SerializePadding(writer io.Writer, rand io.Reader) error {
|
||||
err := serializeHeader(writer, packetPadding, int(pad))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.CopyN(writer, rand, int64(pad))
|
||||
return err
|
||||
}
|
||||
434
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go
generated
vendored
434
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go
generated
vendored
@@ -9,22 +9,28 @@ import (
|
||||
"crypto"
|
||||
"crypto/cipher"
|
||||
"crypto/dsa"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"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/elgamal"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/x25519"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/x448"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
)
|
||||
|
||||
// PrivateKey represents a possibly encrypted private key. See RFC 4880,
|
||||
@@ -35,14 +41,14 @@ type PrivateKey struct {
|
||||
encryptedData []byte
|
||||
cipher CipherFunction
|
||||
s2k func(out, in []byte)
|
||||
// An *{rsa|dsa|elgamal|ecdh|ecdsa|ed25519}.PrivateKey or
|
||||
aead AEADMode // only relevant if S2KAEAD is enabled
|
||||
// An *{rsa|dsa|elgamal|ecdh|ecdsa|ed25519|ed448}.PrivateKey or
|
||||
// crypto.Signer/crypto.Decrypter (Decryptor RSA only).
|
||||
PrivateKey interface{}
|
||||
sha1Checksum bool
|
||||
iv []byte
|
||||
|
||||
// Type of encryption of the S2K packet
|
||||
// Allowed values are 0 (Not encrypted), 254 (SHA1), or
|
||||
// Allowed values are 0 (Not encrypted), 253 (AEAD), 254 (SHA1), or
|
||||
// 255 (2-byte checksum)
|
||||
s2kType S2KType
|
||||
// Full parameters of the S2K packet
|
||||
@@ -55,6 +61,8 @@ type S2KType uint8
|
||||
const (
|
||||
// S2KNON unencrypt
|
||||
S2KNON S2KType = 0
|
||||
// S2KAEAD use authenticated encryption
|
||||
S2KAEAD S2KType = 253
|
||||
// S2KSHA1 sha1 sum check
|
||||
S2KSHA1 S2KType = 254
|
||||
// S2KCHECKSUM sum check
|
||||
@@ -103,6 +111,34 @@ func NewECDHPrivateKey(creationTime time.Time, priv *ecdh.PrivateKey) *PrivateKe
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewX25519PrivateKey(creationTime time.Time, priv *x25519.PrivateKey) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
pk.PublicKey = *NewX25519PublicKey(creationTime, &priv.PublicKey)
|
||||
pk.PrivateKey = priv
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewX448PrivateKey(creationTime time.Time, priv *x448.PrivateKey) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
pk.PublicKey = *NewX448PublicKey(creationTime, &priv.PublicKey)
|
||||
pk.PrivateKey = priv
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewEd25519PrivateKey(creationTime time.Time, priv *ed25519.PrivateKey) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
pk.PublicKey = *NewEd25519PublicKey(creationTime, &priv.PublicKey)
|
||||
pk.PrivateKey = priv
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewEd448PrivateKey(creationTime time.Time, priv *ed448.PrivateKey) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
pk.PublicKey = *NewEd448PublicKey(creationTime, &priv.PublicKey)
|
||||
pk.PrivateKey = priv
|
||||
return pk
|
||||
}
|
||||
|
||||
// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that
|
||||
// implements RSA, ECDSA or EdDSA.
|
||||
func NewSignerPrivateKey(creationTime time.Time, signer interface{}) *PrivateKey {
|
||||
@@ -122,6 +158,14 @@ func NewSignerPrivateKey(creationTime time.Time, signer interface{}) *PrivateKey
|
||||
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pubkey.PublicKey)
|
||||
case eddsa.PrivateKey:
|
||||
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pubkey.PublicKey)
|
||||
case *ed25519.PrivateKey:
|
||||
pk.PublicKey = *NewEd25519PublicKey(creationTime, &pubkey.PublicKey)
|
||||
case ed25519.PrivateKey:
|
||||
pk.PublicKey = *NewEd25519PublicKey(creationTime, &pubkey.PublicKey)
|
||||
case *ed448.PrivateKey:
|
||||
pk.PublicKey = *NewEd448PublicKey(creationTime, &pubkey.PublicKey)
|
||||
case ed448.PrivateKey:
|
||||
pk.PublicKey = *NewEd448PublicKey(creationTime, &pubkey.PublicKey)
|
||||
default:
|
||||
panic("openpgp: unknown signer type in NewSignerPrivateKey")
|
||||
}
|
||||
@@ -129,7 +173,7 @@ func NewSignerPrivateKey(creationTime time.Time, signer interface{}) *PrivateKey
|
||||
return pk
|
||||
}
|
||||
|
||||
// NewDecrypterPrivateKey creates a PrivateKey from a *{rsa|elgamal|ecdh}.PrivateKey.
|
||||
// NewDecrypterPrivateKey creates a PrivateKey from a *{rsa|elgamal|ecdh|x25519|x448}.PrivateKey.
|
||||
func NewDecrypterPrivateKey(creationTime time.Time, decrypter interface{}) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
switch priv := decrypter.(type) {
|
||||
@@ -139,6 +183,10 @@ func NewDecrypterPrivateKey(creationTime time.Time, decrypter interface{}) *Priv
|
||||
pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey)
|
||||
case *ecdh.PrivateKey:
|
||||
pk.PublicKey = *NewECDHPublicKey(creationTime, &priv.PublicKey)
|
||||
case *x25519.PrivateKey:
|
||||
pk.PublicKey = *NewX25519PublicKey(creationTime, &priv.PublicKey)
|
||||
case *x448.PrivateKey:
|
||||
pk.PublicKey = *NewX448PublicKey(creationTime, &priv.PublicKey)
|
||||
default:
|
||||
panic("openpgp: unknown decrypter type in NewDecrypterPrivateKey")
|
||||
}
|
||||
@@ -152,6 +200,11 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
|
||||
return
|
||||
}
|
||||
v5 := pk.PublicKey.Version == 5
|
||||
v6 := pk.PublicKey.Version == 6
|
||||
|
||||
if V5Disabled && v5 {
|
||||
return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed")
|
||||
}
|
||||
|
||||
var buf [1]byte
|
||||
_, err = readFull(r, buf[:])
|
||||
@@ -160,7 +213,7 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
|
||||
}
|
||||
pk.s2kType = S2KType(buf[0])
|
||||
var optCount [1]byte
|
||||
if v5 {
|
||||
if v5 || (v6 && pk.s2kType != S2KNON) {
|
||||
if _, err = readFull(r, optCount[:]); err != nil {
|
||||
return
|
||||
}
|
||||
@@ -170,9 +223,9 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
|
||||
case S2KNON:
|
||||
pk.s2k = nil
|
||||
pk.Encrypted = false
|
||||
case S2KSHA1, S2KCHECKSUM:
|
||||
if v5 && pk.s2kType == S2KCHECKSUM {
|
||||
return errors.StructuralError("wrong s2k identifier for version 5")
|
||||
case S2KSHA1, S2KCHECKSUM, S2KAEAD:
|
||||
if (v5 || v6) && pk.s2kType == S2KCHECKSUM {
|
||||
return errors.StructuralError(fmt.Sprintf("wrong s2k identifier for version %d", pk.Version))
|
||||
}
|
||||
_, err = readFull(r, buf[:])
|
||||
if err != nil {
|
||||
@@ -182,6 +235,29 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
|
||||
if pk.cipher != 0 && !pk.cipher.IsSupported() {
|
||||
return errors.UnsupportedError("unsupported cipher function in private key")
|
||||
}
|
||||
// [Optional] If string-to-key usage octet was 253,
|
||||
// a one-octet AEAD algorithm.
|
||||
if pk.s2kType == S2KAEAD {
|
||||
_, err = readFull(r, buf[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pk.aead = AEADMode(buf[0])
|
||||
if !pk.aead.IsSupported() {
|
||||
return errors.UnsupportedError("unsupported aead mode in private key")
|
||||
}
|
||||
}
|
||||
|
||||
// [Optional] Only for a version 6 packet,
|
||||
// and if string-to-key usage octet was 255, 254, or 253,
|
||||
// an one-octet count of the following field.
|
||||
if v6 {
|
||||
_, err = readFull(r, buf[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
pk.s2kParams, err = s2k.ParseIntoParams(r)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -189,28 +265,43 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
|
||||
if pk.s2kParams.Dummy() {
|
||||
return
|
||||
}
|
||||
if pk.s2kParams.Mode() == s2k.Argon2S2K && pk.s2kType != S2KAEAD {
|
||||
return errors.StructuralError("using Argon2 S2K without AEAD is not allowed")
|
||||
}
|
||||
if pk.s2kParams.Mode() == s2k.SimpleS2K && pk.Version == 6 {
|
||||
return errors.StructuralError("using Simple S2K with version 6 keys is not allowed")
|
||||
}
|
||||
pk.s2k, err = pk.s2kParams.Function()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pk.Encrypted = true
|
||||
if pk.s2kType == S2KSHA1 {
|
||||
pk.sha1Checksum = true
|
||||
}
|
||||
default:
|
||||
return errors.UnsupportedError("deprecated s2k function in private key")
|
||||
}
|
||||
|
||||
if pk.Encrypted {
|
||||
blockSize := pk.cipher.blockSize()
|
||||
if blockSize == 0 {
|
||||
var ivSize int
|
||||
// If the S2K usage octet was 253, the IV is of the size expected by the AEAD mode,
|
||||
// unless it's a version 5 key, in which case it's the size of the symmetric cipher's block size.
|
||||
// For all other S2K modes, it's always the block size.
|
||||
if !v5 && pk.s2kType == S2KAEAD {
|
||||
ivSize = pk.aead.IvLength()
|
||||
} else {
|
||||
ivSize = pk.cipher.blockSize()
|
||||
}
|
||||
|
||||
if ivSize == 0 {
|
||||
return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
|
||||
}
|
||||
pk.iv = make([]byte, blockSize)
|
||||
pk.iv = make([]byte, ivSize)
|
||||
_, err = readFull(r, pk.iv)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if v5 && pk.s2kType == S2KAEAD {
|
||||
pk.iv = pk.iv[:pk.aead.IvLength()]
|
||||
}
|
||||
}
|
||||
|
||||
var privateKeyData []byte
|
||||
@@ -230,7 +321,7 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
privateKeyData, err = ioutil.ReadAll(r)
|
||||
privateKeyData, err = io.ReadAll(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -239,6 +330,8 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
|
||||
if len(privateKeyData) < 2 {
|
||||
return errors.StructuralError("truncated private key data")
|
||||
}
|
||||
if pk.Version != 6 {
|
||||
// checksum
|
||||
var sum uint16
|
||||
for i := 0; i < len(privateKeyData)-2; i++ {
|
||||
sum += uint16(privateKeyData[i])
|
||||
@@ -249,6 +342,10 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
|
||||
}
|
||||
privateKeyData = privateKeyData[:len(privateKeyData)-2]
|
||||
return pk.parsePrivateKey(privateKeyData)
|
||||
} else {
|
||||
// No checksum
|
||||
return pk.parsePrivateKey(privateKeyData)
|
||||
}
|
||||
}
|
||||
|
||||
pk.encryptedData = privateKeyData
|
||||
@@ -280,18 +377,59 @@ func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
|
||||
|
||||
optional := bytes.NewBuffer(nil)
|
||||
if pk.Encrypted || pk.Dummy() {
|
||||
optional.Write([]byte{uint8(pk.cipher)})
|
||||
if err := pk.s2kParams.Serialize(optional); err != nil {
|
||||
// [Optional] If string-to-key usage octet was 255, 254, or 253,
|
||||
// a one-octet symmetric encryption algorithm.
|
||||
if _, err = optional.Write([]byte{uint8(pk.cipher)}); err != nil {
|
||||
return
|
||||
}
|
||||
// [Optional] If string-to-key usage octet was 253,
|
||||
// a one-octet AEAD algorithm.
|
||||
if pk.s2kType == S2KAEAD {
|
||||
if _, err = optional.Write([]byte{uint8(pk.aead)}); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
s2kBuffer := bytes.NewBuffer(nil)
|
||||
if err := pk.s2kParams.Serialize(s2kBuffer); err != nil {
|
||||
return err
|
||||
}
|
||||
// [Optional] Only for a version 6 packet, and if string-to-key
|
||||
// usage octet was 255, 254, or 253, an one-octet
|
||||
// count of the following field.
|
||||
if pk.Version == 6 {
|
||||
if _, err = optional.Write([]byte{uint8(s2kBuffer.Len())}); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
// [Optional] If string-to-key usage octet was 255, 254, or 253,
|
||||
// a string-to-key (S2K) specifier. The length of the string-to-key specifier
|
||||
// depends on its type
|
||||
if _, err = io.Copy(optional, s2kBuffer); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// IV
|
||||
if pk.Encrypted {
|
||||
optional.Write(pk.iv)
|
||||
if _, err = optional.Write(pk.iv); err != nil {
|
||||
return
|
||||
}
|
||||
if pk.Version == 5 && pk.s2kType == S2KAEAD {
|
||||
// Add padding for version 5
|
||||
padding := make([]byte, pk.cipher.blockSize()-len(pk.iv))
|
||||
if _, err = optional.Write(padding); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if pk.Version == 5 {
|
||||
}
|
||||
}
|
||||
if pk.Version == 5 || (pk.Version == 6 && pk.s2kType != S2KNON) {
|
||||
contents.Write([]byte{uint8(optional.Len())})
|
||||
}
|
||||
io.Copy(contents, optional)
|
||||
|
||||
if _, err := io.Copy(contents, optional); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !pk.Dummy() {
|
||||
l := 0
|
||||
@@ -303,8 +441,10 @@ func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
|
||||
return err
|
||||
}
|
||||
l = buf.Len()
|
||||
if pk.Version != 6 {
|
||||
checksum := mod64kHash(buf.Bytes())
|
||||
buf.Write([]byte{byte(checksum >> 8), byte(checksum)})
|
||||
}
|
||||
priv = buf.Bytes()
|
||||
} else {
|
||||
priv, l = pk.encryptedData, len(pk.encryptedData)
|
||||
@@ -370,6 +510,26 @@ func serializeECDHPrivateKey(w io.Writer, priv *ecdh.PrivateKey) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeX25519PrivateKey(w io.Writer, priv *x25519.PrivateKey) error {
|
||||
_, err := w.Write(priv.Secret)
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeX448PrivateKey(w io.Writer, priv *x448.PrivateKey) error {
|
||||
_, err := w.Write(priv.Secret)
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeEd25519PrivateKey(w io.Writer, priv *ed25519.PrivateKey) error {
|
||||
_, err := w.Write(priv.MarshalByteSecret())
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeEd448PrivateKey(w io.Writer, priv *ed448.PrivateKey) error {
|
||||
_, err := w.Write(priv.MarshalByteSecret())
|
||||
return err
|
||||
}
|
||||
|
||||
// decrypt decrypts an encrypted private key using a decryption key.
|
||||
func (pk *PrivateKey) decrypt(decryptionKey []byte) error {
|
||||
if pk.Dummy() {
|
||||
@@ -378,14 +538,25 @@ func (pk *PrivateKey) decrypt(decryptionKey []byte) error {
|
||||
if !pk.Encrypted {
|
||||
return nil
|
||||
}
|
||||
|
||||
block := pk.cipher.new(decryptionKey)
|
||||
var data []byte
|
||||
switch pk.s2kType {
|
||||
case S2KAEAD:
|
||||
aead := pk.aead.new(block)
|
||||
additionalData, err := pk.additionalData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Decrypt the encrypted key material with aead
|
||||
data, err = aead.Open(nil, pk.iv, pk.encryptedData, additionalData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case S2KSHA1, S2KCHECKSUM:
|
||||
cfb := cipher.NewCFBDecrypter(block, pk.iv)
|
||||
|
||||
data := make([]byte, len(pk.encryptedData))
|
||||
data = make([]byte, len(pk.encryptedData))
|
||||
cfb.XORKeyStream(data, pk.encryptedData)
|
||||
|
||||
if pk.sha1Checksum {
|
||||
if pk.s2kType == S2KSHA1 {
|
||||
if len(data) < sha1.Size {
|
||||
return errors.StructuralError("truncated private key data")
|
||||
}
|
||||
@@ -410,6 +581,9 @@ func (pk *PrivateKey) decrypt(decryptionKey []byte) error {
|
||||
}
|
||||
data = data[:len(data)-2]
|
||||
}
|
||||
default:
|
||||
return errors.InvalidArgumentError("invalid s2k type")
|
||||
}
|
||||
|
||||
err := pk.parsePrivateKey(data)
|
||||
if _, ok := err.(errors.KeyInvalidError); ok {
|
||||
@@ -424,7 +598,6 @@ func (pk *PrivateKey) decrypt(decryptionKey []byte) error {
|
||||
pk.s2k = nil
|
||||
pk.Encrypted = false
|
||||
pk.encryptedData = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -440,6 +613,9 @@ func (pk *PrivateKey) decryptWithCache(passphrase []byte, keyCache *s2k.Cache) e
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pk.s2kType == S2KAEAD {
|
||||
key = pk.applyHKDF(key)
|
||||
}
|
||||
return pk.decrypt(key)
|
||||
}
|
||||
|
||||
@@ -454,6 +630,9 @@ func (pk *PrivateKey) Decrypt(passphrase []byte) error {
|
||||
|
||||
key := make([]byte, pk.cipher.KeySize())
|
||||
pk.s2k(key, passphrase)
|
||||
if pk.s2kType == S2KAEAD {
|
||||
key = pk.applyHKDF(key)
|
||||
}
|
||||
return pk.decrypt(key)
|
||||
}
|
||||
|
||||
@@ -474,7 +653,7 @@ func DecryptPrivateKeys(keys []*PrivateKey, passphrase []byte) error {
|
||||
}
|
||||
|
||||
// encrypt encrypts an unencrypted private key.
|
||||
func (pk *PrivateKey) encrypt(key []byte, params *s2k.Params, cipherFunction CipherFunction) error {
|
||||
func (pk *PrivateKey) encrypt(key []byte, params *s2k.Params, s2kType S2KType, cipherFunction CipherFunction, rand io.Reader) error {
|
||||
if pk.Dummy() {
|
||||
return errors.ErrDummyPrivateKey("dummy key found")
|
||||
}
|
||||
@@ -486,6 +665,14 @@ func (pk *PrivateKey) encrypt(key []byte, params *s2k.Params, cipherFunction Cip
|
||||
return errors.InvalidArgumentError("supplied encryption key has the wrong size")
|
||||
}
|
||||
|
||||
if params.Mode() == s2k.Argon2S2K && s2kType != S2KAEAD {
|
||||
return errors.InvalidArgumentError("using Argon2 S2K without AEAD is not allowed")
|
||||
}
|
||||
if params.Mode() != s2k.Argon2S2K && params.Mode() != s2k.IteratedSaltedS2K &&
|
||||
params.Mode() != s2k.SaltedS2K { // only allowed for high-entropy passphrases
|
||||
return errors.InvalidArgumentError("insecure S2K mode")
|
||||
}
|
||||
|
||||
priv := bytes.NewBuffer(nil)
|
||||
err := pk.serializePrivateKey(priv)
|
||||
if err != nil {
|
||||
@@ -500,32 +687,50 @@ func (pk *PrivateKey) encrypt(key []byte, params *s2k.Params, cipherFunction Cip
|
||||
}
|
||||
|
||||
privateKeyBytes := priv.Bytes()
|
||||
pk.sha1Checksum = true
|
||||
pk.s2kType = s2kType
|
||||
block := pk.cipher.new(key)
|
||||
switch s2kType {
|
||||
case S2KAEAD:
|
||||
if pk.aead == 0 {
|
||||
return errors.StructuralError("aead mode is not set on key")
|
||||
}
|
||||
aead := pk.aead.new(block)
|
||||
additionalData, err := pk.additionalData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pk.iv = make([]byte, aead.NonceSize())
|
||||
_, err = io.ReadFull(rand, pk.iv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Decrypt the encrypted key material with aead
|
||||
pk.encryptedData = aead.Seal(nil, pk.iv, privateKeyBytes, additionalData)
|
||||
case S2KSHA1, S2KCHECKSUM:
|
||||
pk.iv = make([]byte, pk.cipher.blockSize())
|
||||
_, err = rand.Read(pk.iv)
|
||||
_, err = io.ReadFull(rand, pk.iv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfb := cipher.NewCFBEncrypter(block, pk.iv)
|
||||
|
||||
if pk.sha1Checksum {
|
||||
pk.s2kType = S2KSHA1
|
||||
if s2kType == S2KSHA1 {
|
||||
h := sha1.New()
|
||||
h.Write(privateKeyBytes)
|
||||
sum := h.Sum(nil)
|
||||
privateKeyBytes = append(privateKeyBytes, sum...)
|
||||
} else {
|
||||
pk.s2kType = S2KCHECKSUM
|
||||
var sum uint16
|
||||
for _, b := range privateKeyBytes {
|
||||
sum += uint16(b)
|
||||
}
|
||||
priv.Write([]byte{uint8(sum >> 8), uint8(sum)})
|
||||
privateKeyBytes = append(privateKeyBytes, []byte{uint8(sum >> 8), uint8(sum)}...)
|
||||
}
|
||||
|
||||
pk.encryptedData = make([]byte, len(privateKeyBytes))
|
||||
cfb.XORKeyStream(pk.encryptedData, privateKeyBytes)
|
||||
default:
|
||||
return errors.InvalidArgumentError("invalid s2k type for encryption")
|
||||
}
|
||||
|
||||
pk.Encrypted = true
|
||||
pk.PrivateKey = nil
|
||||
return err
|
||||
@@ -544,8 +749,15 @@ func (pk *PrivateKey) EncryptWithConfig(passphrase []byte, config *Config) error
|
||||
return err
|
||||
}
|
||||
s2k(key, passphrase)
|
||||
s2kType := S2KSHA1
|
||||
if config.AEAD() != nil {
|
||||
s2kType = S2KAEAD
|
||||
pk.aead = config.AEAD().Mode()
|
||||
pk.cipher = config.Cipher()
|
||||
key = pk.applyHKDF(key)
|
||||
}
|
||||
// Encrypt the private key with the derived encryption key.
|
||||
return pk.encrypt(key, params, config.Cipher())
|
||||
return pk.encrypt(key, params, s2kType, config.Cipher(), config.Random())
|
||||
}
|
||||
|
||||
// EncryptPrivateKeys encrypts all unencrypted keys with the given config and passphrase.
|
||||
@@ -564,7 +776,16 @@ func EncryptPrivateKeys(keys []*PrivateKey, passphrase []byte, config *Config) e
|
||||
s2k(encryptionKey, passphrase)
|
||||
for _, key := range keys {
|
||||
if key != nil && !key.Dummy() && !key.Encrypted {
|
||||
err = key.encrypt(encryptionKey, params, config.Cipher())
|
||||
s2kType := S2KSHA1
|
||||
if config.AEAD() != nil {
|
||||
s2kType = S2KAEAD
|
||||
key.aead = config.AEAD().Mode()
|
||||
key.cipher = config.Cipher()
|
||||
derivedKey := key.applyHKDF(encryptionKey)
|
||||
err = key.encrypt(derivedKey, params, s2kType, config.Cipher(), config.Random())
|
||||
} else {
|
||||
err = key.encrypt(encryptionKey, params, s2kType, config.Cipher(), config.Random())
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -601,6 +822,14 @@ func (pk *PrivateKey) serializePrivateKey(w io.Writer) (err error) {
|
||||
err = serializeEdDSAPrivateKey(w, priv)
|
||||
case *ecdh.PrivateKey:
|
||||
err = serializeECDHPrivateKey(w, priv)
|
||||
case *x25519.PrivateKey:
|
||||
err = serializeX25519PrivateKey(w, priv)
|
||||
case *x448.PrivateKey:
|
||||
err = serializeX448PrivateKey(w, priv)
|
||||
case *ed25519.PrivateKey:
|
||||
err = serializeEd25519PrivateKey(w, priv)
|
||||
case *ed448.PrivateKey:
|
||||
err = serializeEd448PrivateKey(w, priv)
|
||||
default:
|
||||
err = errors.InvalidArgumentError("unknown private key type")
|
||||
}
|
||||
@@ -621,8 +850,18 @@ func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
|
||||
return pk.parseECDHPrivateKey(data)
|
||||
case PubKeyAlgoEdDSA:
|
||||
return pk.parseEdDSAPrivateKey(data)
|
||||
case PubKeyAlgoX25519:
|
||||
return pk.parseX25519PrivateKey(data)
|
||||
case PubKeyAlgoX448:
|
||||
return pk.parseX448PrivateKey(data)
|
||||
case PubKeyAlgoEd25519:
|
||||
return pk.parseEd25519PrivateKey(data)
|
||||
case PubKeyAlgoEd448:
|
||||
return pk.parseEd448PrivateKey(data)
|
||||
default:
|
||||
err = errors.StructuralError("unknown private key type")
|
||||
return
|
||||
}
|
||||
panic("impossible")
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
|
||||
@@ -743,6 +982,86 @@ func (pk *PrivateKey) parseECDHPrivateKey(data []byte) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseX25519PrivateKey(data []byte) (err error) {
|
||||
publicKey := pk.PublicKey.PublicKey.(*x25519.PublicKey)
|
||||
privateKey := x25519.NewPrivateKey(*publicKey)
|
||||
privateKey.PublicKey = *publicKey
|
||||
|
||||
privateKey.Secret = make([]byte, x25519.KeySize)
|
||||
|
||||
if len(data) != x25519.KeySize {
|
||||
err = errors.StructuralError("wrong x25519 key size")
|
||||
return err
|
||||
}
|
||||
subtle.ConstantTimeCopy(1, privateKey.Secret, data)
|
||||
if err = x25519.Validate(privateKey); err != nil {
|
||||
return err
|
||||
}
|
||||
pk.PrivateKey = privateKey
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseX448PrivateKey(data []byte) (err error) {
|
||||
publicKey := pk.PublicKey.PublicKey.(*x448.PublicKey)
|
||||
privateKey := x448.NewPrivateKey(*publicKey)
|
||||
privateKey.PublicKey = *publicKey
|
||||
|
||||
privateKey.Secret = make([]byte, x448.KeySize)
|
||||
|
||||
if len(data) != x448.KeySize {
|
||||
err = errors.StructuralError("wrong x448 key size")
|
||||
return err
|
||||
}
|
||||
subtle.ConstantTimeCopy(1, privateKey.Secret, data)
|
||||
if err = x448.Validate(privateKey); err != nil {
|
||||
return err
|
||||
}
|
||||
pk.PrivateKey = privateKey
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseEd25519PrivateKey(data []byte) (err error) {
|
||||
publicKey := pk.PublicKey.PublicKey.(*ed25519.PublicKey)
|
||||
privateKey := ed25519.NewPrivateKey(*publicKey)
|
||||
privateKey.PublicKey = *publicKey
|
||||
|
||||
if len(data) != ed25519.SeedSize {
|
||||
err = errors.StructuralError("wrong ed25519 key size")
|
||||
return err
|
||||
}
|
||||
err = privateKey.UnmarshalByteSecret(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ed25519.Validate(privateKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pk.PrivateKey = privateKey
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseEd448PrivateKey(data []byte) (err error) {
|
||||
publicKey := pk.PublicKey.PublicKey.(*ed448.PublicKey)
|
||||
privateKey := ed448.NewPrivateKey(*publicKey)
|
||||
privateKey.PublicKey = *publicKey
|
||||
|
||||
if len(data) != ed448.SeedSize {
|
||||
err = errors.StructuralError("wrong ed448 key size")
|
||||
return err
|
||||
}
|
||||
err = privateKey.UnmarshalByteSecret(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ed448.Validate(privateKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pk.PrivateKey = privateKey
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseEdDSAPrivateKey(data []byte) (err error) {
|
||||
eddsaPub := pk.PublicKey.PublicKey.(*eddsa.PublicKey)
|
||||
eddsaPriv := eddsa.NewPrivateKey(*eddsaPub)
|
||||
@@ -767,6 +1086,41 @@ func (pk *PrivateKey) parseEdDSAPrivateKey(data []byte) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) additionalData() ([]byte, error) {
|
||||
additionalData := bytes.NewBuffer(nil)
|
||||
// Write additional data prefix based on packet type
|
||||
var packetByte byte
|
||||
if pk.PublicKey.IsSubkey {
|
||||
packetByte = 0xc7
|
||||
} else {
|
||||
packetByte = 0xc5
|
||||
}
|
||||
// Write public key to additional data
|
||||
_, err := additionalData.Write([]byte{packetByte})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = pk.PublicKey.serializeWithoutHeaders(additionalData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return additionalData.Bytes(), nil
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) applyHKDF(inputKey []byte) []byte {
|
||||
var packetByte byte
|
||||
if pk.PublicKey.IsSubkey {
|
||||
packetByte = 0xc7
|
||||
} else {
|
||||
packetByte = 0xc5
|
||||
}
|
||||
associatedData := []byte{packetByte, byte(pk.Version), byte(pk.cipher), byte(pk.aead)}
|
||||
hkdfReader := hkdf.New(sha256.New, inputKey, []byte{}, associatedData)
|
||||
encryptionKey := make([]byte, pk.cipher.KeySize())
|
||||
_, _ = readFull(hkdfReader, encryptionKey)
|
||||
return encryptionKey
|
||||
}
|
||||
|
||||
func validateDSAParameters(priv *dsa.PrivateKey) error {
|
||||
p := priv.P // group prime
|
||||
q := priv.Q // subgroup order
|
||||
|
||||
487
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go
generated
vendored
487
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go
generated
vendored
@@ -5,7 +5,6 @@
|
||||
package packet
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/dsa"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
@@ -21,23 +20,24 @@ import (
|
||||
|
||||
"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/elgamal"
|
||||
"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/internal/encoding"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/x25519"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/x448"
|
||||
)
|
||||
|
||||
type kdfHashFunction byte
|
||||
type kdfAlgorithm byte
|
||||
|
||||
// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
|
||||
type PublicKey struct {
|
||||
Version int
|
||||
CreationTime time.Time
|
||||
PubKeyAlgo PublicKeyAlgorithm
|
||||
PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or *eddsa.PublicKey
|
||||
PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or *eddsa.PublicKey, *x25519.PublicKey, *x448.PublicKey, *ed25519.PublicKey, *ed448.PublicKey
|
||||
Fingerprint []byte
|
||||
KeyId uint64
|
||||
IsSubkey bool
|
||||
@@ -61,11 +61,19 @@ func (pk *PublicKey) UpgradeToV5() {
|
||||
pk.setFingerprintAndKeyId()
|
||||
}
|
||||
|
||||
// UpgradeToV6 updates the version of the key to v6, and updates all necessary
|
||||
// fields.
|
||||
func (pk *PublicKey) UpgradeToV6() error {
|
||||
pk.Version = 6
|
||||
pk.setFingerprintAndKeyId()
|
||||
return pk.checkV6Compatibility()
|
||||
}
|
||||
|
||||
// signingKey provides a convenient abstraction over signature verification
|
||||
// for v3 and v4 public keys.
|
||||
type signingKey interface {
|
||||
SerializeForHash(io.Writer) error
|
||||
SerializeSignaturePrefix(io.Writer)
|
||||
SerializeSignaturePrefix(io.Writer) error
|
||||
serializeWithoutHeaders(io.Writer) error
|
||||
}
|
||||
|
||||
@@ -174,6 +182,54 @@ func NewEdDSAPublicKey(creationTime time.Time, pub *eddsa.PublicKey) *PublicKey
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewX25519PublicKey(creationTime time.Time, pub *x25519.PublicKey) *PublicKey {
|
||||
pk := &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoX25519,
|
||||
PublicKey: pub,
|
||||
}
|
||||
|
||||
pk.setFingerprintAndKeyId()
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewX448PublicKey(creationTime time.Time, pub *x448.PublicKey) *PublicKey {
|
||||
pk := &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoX448,
|
||||
PublicKey: pub,
|
||||
}
|
||||
|
||||
pk.setFingerprintAndKeyId()
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewEd25519PublicKey(creationTime time.Time, pub *ed25519.PublicKey) *PublicKey {
|
||||
pk := &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoEd25519,
|
||||
PublicKey: pub,
|
||||
}
|
||||
|
||||
pk.setFingerprintAndKeyId()
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewEd448PublicKey(creationTime time.Time, pub *ed448.PublicKey) *PublicKey {
|
||||
pk := &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoEd448,
|
||||
PublicKey: pub,
|
||||
}
|
||||
|
||||
pk.setFingerprintAndKeyId()
|
||||
return pk
|
||||
}
|
||||
|
||||
func (pk *PublicKey) parse(r io.Reader) (err error) {
|
||||
// RFC 4880, section 5.5.2
|
||||
var buf [6]byte
|
||||
@@ -181,12 +237,19 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if buf[0] != 4 && buf[0] != 5 {
|
||||
|
||||
pk.Version = int(buf[0])
|
||||
if pk.Version != 4 && pk.Version != 5 && pk.Version != 6 {
|
||||
return errors.UnsupportedError("public key version " + strconv.Itoa(int(buf[0])))
|
||||
}
|
||||
|
||||
pk.Version = int(buf[0])
|
||||
if pk.Version == 5 {
|
||||
if V5Disabled && pk.Version == 5 {
|
||||
return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed")
|
||||
}
|
||||
|
||||
if pk.Version >= 5 {
|
||||
// Read the four-octet scalar octet count
|
||||
// The count is not used in this implementation
|
||||
var n [4]byte
|
||||
_, err = readFull(r, n[:])
|
||||
if err != nil {
|
||||
@@ -195,6 +258,7 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
|
||||
}
|
||||
pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
|
||||
pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
|
||||
// Ignore four-ocet length
|
||||
switch pk.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
||||
err = pk.parseRSA(r)
|
||||
@@ -208,6 +272,14 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
|
||||
err = pk.parseECDH(r)
|
||||
case PubKeyAlgoEdDSA:
|
||||
err = pk.parseEdDSA(r)
|
||||
case PubKeyAlgoX25519:
|
||||
err = pk.parseX25519(r)
|
||||
case PubKeyAlgoX448:
|
||||
err = pk.parseX448(r)
|
||||
case PubKeyAlgoEd25519:
|
||||
err = pk.parseEd25519(r)
|
||||
case PubKeyAlgoEd448:
|
||||
err = pk.parseEd448(r)
|
||||
default:
|
||||
err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
|
||||
}
|
||||
@@ -221,21 +293,44 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
|
||||
|
||||
func (pk *PublicKey) setFingerprintAndKeyId() {
|
||||
// RFC 4880, section 12.2
|
||||
if pk.Version == 5 {
|
||||
if pk.Version >= 5 {
|
||||
fingerprint := sha256.New()
|
||||
pk.SerializeForHash(fingerprint)
|
||||
if err := pk.SerializeForHash(fingerprint); err != nil {
|
||||
// Should not happen for a hash.
|
||||
panic(err)
|
||||
}
|
||||
pk.Fingerprint = make([]byte, 32)
|
||||
copy(pk.Fingerprint, fingerprint.Sum(nil))
|
||||
pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[:8])
|
||||
} else {
|
||||
fingerprint := sha1.New()
|
||||
pk.SerializeForHash(fingerprint)
|
||||
if err := pk.SerializeForHash(fingerprint); err != nil {
|
||||
// Should not happen for a hash.
|
||||
panic(err)
|
||||
}
|
||||
pk.Fingerprint = make([]byte, 20)
|
||||
copy(pk.Fingerprint, fingerprint.Sum(nil))
|
||||
pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
|
||||
}
|
||||
}
|
||||
|
||||
func (pk *PublicKey) checkV6Compatibility() error {
|
||||
// Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs.
|
||||
switch pk.PubKeyAlgo {
|
||||
case PubKeyAlgoECDH:
|
||||
curveInfo := ecc.FindByOid(pk.oid)
|
||||
if curveInfo == nil {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
|
||||
}
|
||||
if curveInfo.GenName == ecc.Curve25519GenName {
|
||||
return errors.StructuralError("cannot generate v6 key with deprecated OID: Curve25519Legacy")
|
||||
}
|
||||
case PubKeyAlgoEdDSA:
|
||||
return errors.StructuralError("cannot generate v6 key with deprecated algorithm: EdDSALegacy")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
|
||||
// section 5.5.2.
|
||||
func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
|
||||
@@ -324,16 +419,17 @@ func (pk *PublicKey) parseECDSA(r io.Reader) (err error) {
|
||||
if _, err = pk.oid.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
pk.p = new(encoding.MPI)
|
||||
if _, err = pk.p.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
curveInfo := ecc.FindByOid(pk.oid)
|
||||
if curveInfo == nil {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
|
||||
}
|
||||
|
||||
pk.p = new(encoding.MPI)
|
||||
if _, err = pk.p.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c, ok := curveInfo.Curve.(ecc.ECDSACurve)
|
||||
if !ok {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
|
||||
@@ -353,6 +449,17 @@ func (pk *PublicKey) parseECDH(r io.Reader) (err error) {
|
||||
if _, err = pk.oid.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
curveInfo := ecc.FindByOid(pk.oid)
|
||||
if curveInfo == nil {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
|
||||
}
|
||||
|
||||
if pk.Version == 6 && curveInfo.GenName == ecc.Curve25519GenName {
|
||||
// Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs.
|
||||
return errors.StructuralError("cannot read v6 key with deprecated OID: Curve25519Legacy")
|
||||
}
|
||||
|
||||
pk.p = new(encoding.MPI)
|
||||
if _, err = pk.p.ReadFrom(r); err != nil {
|
||||
return
|
||||
@@ -362,12 +469,6 @@ func (pk *PublicKey) parseECDH(r io.Reader) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
curveInfo := ecc.FindByOid(pk.oid)
|
||||
|
||||
if curveInfo == nil {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
|
||||
}
|
||||
|
||||
c, ok := curveInfo.Curve.(ecc.ECDHCurve)
|
||||
if !ok {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
|
||||
@@ -396,10 +497,16 @@ func (pk *PublicKey) parseECDH(r io.Reader) (err error) {
|
||||
}
|
||||
|
||||
func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) {
|
||||
if pk.Version == 6 {
|
||||
// Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs.
|
||||
return errors.StructuralError("cannot generate v6 key with deprecated algorithm: EdDSALegacy")
|
||||
}
|
||||
|
||||
pk.oid = new(encoding.OID)
|
||||
if _, err = pk.oid.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
curveInfo := ecc.FindByOid(pk.oid)
|
||||
if curveInfo == nil {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
|
||||
@@ -435,75 +542,145 @@ func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (pk *PublicKey) parseX25519(r io.Reader) (err error) {
|
||||
point := make([]byte, x25519.KeySize)
|
||||
_, err = io.ReadFull(r, point)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pub := &x25519.PublicKey{
|
||||
Point: point,
|
||||
}
|
||||
pk.PublicKey = pub
|
||||
return
|
||||
}
|
||||
|
||||
func (pk *PublicKey) parseX448(r io.Reader) (err error) {
|
||||
point := make([]byte, x448.KeySize)
|
||||
_, err = io.ReadFull(r, point)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pub := &x448.PublicKey{
|
||||
Point: point,
|
||||
}
|
||||
pk.PublicKey = pub
|
||||
return
|
||||
}
|
||||
|
||||
func (pk *PublicKey) parseEd25519(r io.Reader) (err error) {
|
||||
point := make([]byte, ed25519.PublicKeySize)
|
||||
_, err = io.ReadFull(r, point)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pub := &ed25519.PublicKey{
|
||||
Point: point,
|
||||
}
|
||||
pk.PublicKey = pub
|
||||
return
|
||||
}
|
||||
|
||||
func (pk *PublicKey) parseEd448(r io.Reader) (err error) {
|
||||
point := make([]byte, ed448.PublicKeySize)
|
||||
_, err = io.ReadFull(r, point)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pub := &ed448.PublicKey{
|
||||
Point: point,
|
||||
}
|
||||
pk.PublicKey = pub
|
||||
return
|
||||
}
|
||||
|
||||
// SerializeForHash serializes the PublicKey to w with the special packet
|
||||
// header format needed for hashing.
|
||||
func (pk *PublicKey) SerializeForHash(w io.Writer) error {
|
||||
pk.SerializeSignaturePrefix(w)
|
||||
if err := pk.SerializeSignaturePrefix(w); err != nil {
|
||||
return err
|
||||
}
|
||||
return pk.serializeWithoutHeaders(w)
|
||||
}
|
||||
|
||||
// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
|
||||
// The prefix is used when calculating a signature over this public key. See
|
||||
// RFC 4880, section 5.2.4.
|
||||
func (pk *PublicKey) SerializeSignaturePrefix(w io.Writer) {
|
||||
func (pk *PublicKey) SerializeSignaturePrefix(w io.Writer) error {
|
||||
var pLength = pk.algorithmSpecificByteCount()
|
||||
if pk.Version == 5 {
|
||||
pLength += 10 // version, timestamp (4), algorithm, key octet count (4).
|
||||
w.Write([]byte{
|
||||
0x9A,
|
||||
// version, timestamp, algorithm
|
||||
pLength += versionSize + timestampSize + algorithmSize
|
||||
if pk.Version >= 5 {
|
||||
// key octet count (4).
|
||||
pLength += 4
|
||||
_, err := w.Write([]byte{
|
||||
// When a v4 signature is made over a key, the hash data starts with the octet 0x99, followed by a two-octet length
|
||||
// of the key, and then the body of the key packet. When a v6 signature is made over a key, the hash data starts
|
||||
// with the salt, then octet 0x9B, followed by a four-octet length of the key, and then the body of the key packet.
|
||||
0x95 + byte(pk.Version),
|
||||
byte(pLength >> 24),
|
||||
byte(pLength >> 16),
|
||||
byte(pLength >> 8),
|
||||
byte(pLength),
|
||||
})
|
||||
return
|
||||
return err
|
||||
}
|
||||
pLength += 6
|
||||
w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
|
||||
if _, err := w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pk *PublicKey) Serialize(w io.Writer) (err error) {
|
||||
length := 6 // 6 byte header
|
||||
length := uint32(versionSize + timestampSize + algorithmSize) // 6 byte header
|
||||
length += pk.algorithmSpecificByteCount()
|
||||
if pk.Version == 5 {
|
||||
if pk.Version >= 5 {
|
||||
length += 4 // octet key count
|
||||
}
|
||||
packetType := packetTypePublicKey
|
||||
if pk.IsSubkey {
|
||||
packetType = packetTypePublicSubkey
|
||||
}
|
||||
err = serializeHeader(w, packetType, length)
|
||||
err = serializeHeader(w, packetType, int(length))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return pk.serializeWithoutHeaders(w)
|
||||
}
|
||||
|
||||
func (pk *PublicKey) algorithmSpecificByteCount() int {
|
||||
length := 0
|
||||
func (pk *PublicKey) algorithmSpecificByteCount() uint32 {
|
||||
length := uint32(0)
|
||||
switch pk.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
||||
length += int(pk.n.EncodedLength())
|
||||
length += int(pk.e.EncodedLength())
|
||||
length += uint32(pk.n.EncodedLength())
|
||||
length += uint32(pk.e.EncodedLength())
|
||||
case PubKeyAlgoDSA:
|
||||
length += int(pk.p.EncodedLength())
|
||||
length += int(pk.q.EncodedLength())
|
||||
length += int(pk.g.EncodedLength())
|
||||
length += int(pk.y.EncodedLength())
|
||||
length += uint32(pk.p.EncodedLength())
|
||||
length += uint32(pk.q.EncodedLength())
|
||||
length += uint32(pk.g.EncodedLength())
|
||||
length += uint32(pk.y.EncodedLength())
|
||||
case PubKeyAlgoElGamal:
|
||||
length += int(pk.p.EncodedLength())
|
||||
length += int(pk.g.EncodedLength())
|
||||
length += int(pk.y.EncodedLength())
|
||||
length += uint32(pk.p.EncodedLength())
|
||||
length += uint32(pk.g.EncodedLength())
|
||||
length += uint32(pk.y.EncodedLength())
|
||||
case PubKeyAlgoECDSA:
|
||||
length += int(pk.oid.EncodedLength())
|
||||
length += int(pk.p.EncodedLength())
|
||||
length += uint32(pk.oid.EncodedLength())
|
||||
length += uint32(pk.p.EncodedLength())
|
||||
case PubKeyAlgoECDH:
|
||||
length += int(pk.oid.EncodedLength())
|
||||
length += int(pk.p.EncodedLength())
|
||||
length += int(pk.kdf.EncodedLength())
|
||||
length += uint32(pk.oid.EncodedLength())
|
||||
length += uint32(pk.p.EncodedLength())
|
||||
length += uint32(pk.kdf.EncodedLength())
|
||||
case PubKeyAlgoEdDSA:
|
||||
length += int(pk.oid.EncodedLength())
|
||||
length += int(pk.p.EncodedLength())
|
||||
length += uint32(pk.oid.EncodedLength())
|
||||
length += uint32(pk.p.EncodedLength())
|
||||
case PubKeyAlgoX25519:
|
||||
length += x25519.KeySize
|
||||
case PubKeyAlgoX448:
|
||||
length += x448.KeySize
|
||||
case PubKeyAlgoEd25519:
|
||||
length += ed25519.PublicKeySize
|
||||
case PubKeyAlgoEd448:
|
||||
length += ed448.PublicKeySize
|
||||
default:
|
||||
panic("unknown public key algorithm")
|
||||
}
|
||||
@@ -522,7 +699,7 @@ func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if pk.Version == 5 {
|
||||
if pk.Version >= 5 {
|
||||
n := pk.algorithmSpecificByteCount()
|
||||
if _, err = w.Write([]byte{
|
||||
byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n),
|
||||
@@ -580,6 +757,22 @@ func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
|
||||
}
|
||||
_, err = w.Write(pk.p.EncodedBytes())
|
||||
return
|
||||
case PubKeyAlgoX25519:
|
||||
publicKey := pk.PublicKey.(*x25519.PublicKey)
|
||||
_, err = w.Write(publicKey.Point)
|
||||
return
|
||||
case PubKeyAlgoX448:
|
||||
publicKey := pk.PublicKey.(*x448.PublicKey)
|
||||
_, err = w.Write(publicKey.Point)
|
||||
return
|
||||
case PubKeyAlgoEd25519:
|
||||
publicKey := pk.PublicKey.(*ed25519.PublicKey)
|
||||
_, err = w.Write(publicKey.Point)
|
||||
return
|
||||
case PubKeyAlgoEd448:
|
||||
publicKey := pk.PublicKey.(*ed448.PublicKey)
|
||||
_, err = w.Write(publicKey.Point)
|
||||
return
|
||||
}
|
||||
return errors.InvalidArgumentError("bad public-key algorithm")
|
||||
}
|
||||
@@ -589,6 +782,20 @@ func (pk *PublicKey) CanSign() bool {
|
||||
return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal && pk.PubKeyAlgo != PubKeyAlgoECDH
|
||||
}
|
||||
|
||||
// VerifyHashTag returns nil iff sig appears to be a plausible signature of the data
|
||||
// hashed into signed, based solely on its HashTag. signed is mutated by this call.
|
||||
func VerifyHashTag(signed hash.Hash, sig *Signature) (err error) {
|
||||
if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) {
|
||||
sig.AddMetadataToHashSuffix()
|
||||
}
|
||||
signed.Write(sig.HashSuffix)
|
||||
hashBytes := signed.Sum(nil)
|
||||
if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
|
||||
return errors.SignatureError("hash tag doesn't match")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifySignature returns nil iff sig is a valid signature, made by this
|
||||
// public key, of the data hashed into signed. signed is mutated by this call.
|
||||
func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
|
||||
@@ -600,7 +807,8 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
|
||||
}
|
||||
signed.Write(sig.HashSuffix)
|
||||
hashBytes := signed.Sum(nil)
|
||||
if sig.Version == 5 && (hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1]) {
|
||||
// see discussion https://github.com/ProtonMail/go-crypto/issues/107
|
||||
if sig.Version >= 5 && (hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1]) {
|
||||
return errors.SignatureError("hash tag doesn't match")
|
||||
}
|
||||
|
||||
@@ -639,6 +847,18 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
|
||||
return errors.SignatureError("EdDSA verification failure")
|
||||
}
|
||||
return nil
|
||||
case PubKeyAlgoEd25519:
|
||||
ed25519PublicKey := pk.PublicKey.(*ed25519.PublicKey)
|
||||
if !ed25519.Verify(ed25519PublicKey, hashBytes, sig.EdSig) {
|
||||
return errors.SignatureError("Ed25519 verification failure")
|
||||
}
|
||||
return nil
|
||||
case PubKeyAlgoEd448:
|
||||
ed448PublicKey := pk.PublicKey.(*ed448.PublicKey)
|
||||
if !ed448.Verify(ed448PublicKey, hashBytes, sig.EdSig) {
|
||||
return errors.SignatureError("ed448 verification failure")
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return errors.SignatureError("Unsupported public key algorithm used in signature")
|
||||
}
|
||||
@@ -646,11 +866,8 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
|
||||
|
||||
// keySignatureHash returns a Hash of the message that needs to be signed for
|
||||
// pk to assert a subkey relationship to signed.
|
||||
func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
|
||||
if !hashFunc.Available() {
|
||||
return nil, errors.UnsupportedError("hash function")
|
||||
}
|
||||
h = hashFunc.New()
|
||||
func keySignatureHash(pk, signed signingKey, hashFunc hash.Hash) (h hash.Hash, err error) {
|
||||
h = hashFunc
|
||||
|
||||
// RFC 4880, section 5.2.4
|
||||
err = pk.SerializeForHash(h)
|
||||
@@ -662,10 +879,28 @@ func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash,
|
||||
return
|
||||
}
|
||||
|
||||
// VerifyKeyHashTag returns nil iff sig appears to be a plausible signature over this
|
||||
// primary key and subkey, based solely on its HashTag.
|
||||
func (pk *PublicKey) VerifyKeyHashTag(signed *PublicKey, sig *Signature) error {
|
||||
preparedHash, err := sig.PrepareVerify()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h, err := keySignatureHash(pk, signed, preparedHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return VerifyHashTag(h, sig)
|
||||
}
|
||||
|
||||
// VerifyKeySignature returns nil iff sig is a valid signature, made by this
|
||||
// public key, of signed.
|
||||
func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error {
|
||||
h, err := keySignatureHash(pk, signed, sig.Hash)
|
||||
preparedHash, err := sig.PrepareVerify()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h, err := keySignatureHash(pk, signed, preparedHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -679,10 +914,14 @@ func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error
|
||||
if sig.EmbeddedSignature == nil {
|
||||
return errors.StructuralError("signing subkey is missing cross-signature")
|
||||
}
|
||||
preparedHashEmbedded, err := sig.EmbeddedSignature.PrepareVerify()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Verify the cross-signature. This is calculated over the same
|
||||
// data as the main signature, so we cannot just recursively
|
||||
// call signed.VerifyKeySignature(...)
|
||||
if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil {
|
||||
if h, err = keySignatureHash(pk, signed, preparedHashEmbedded); err != nil {
|
||||
return errors.StructuralError("error while hashing for cross-signature: " + err.Error())
|
||||
}
|
||||
if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil {
|
||||
@@ -693,32 +932,44 @@ func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
|
||||
if !hashFunc.Available() {
|
||||
return nil, errors.UnsupportedError("hash function")
|
||||
func keyRevocationHash(pk signingKey, hashFunc hash.Hash) (err error) {
|
||||
return pk.SerializeForHash(hashFunc)
|
||||
}
|
||||
h = hashFunc.New()
|
||||
|
||||
// RFC 4880, section 5.2.4
|
||||
err = pk.SerializeForHash(h)
|
||||
|
||||
return
|
||||
// VerifyRevocationHashTag returns nil iff sig appears to be a plausible signature
|
||||
// over this public key, based solely on its HashTag.
|
||||
func (pk *PublicKey) VerifyRevocationHashTag(sig *Signature) (err error) {
|
||||
preparedHash, err := sig.PrepareVerify()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = keyRevocationHash(pk, preparedHash); err != nil {
|
||||
return err
|
||||
}
|
||||
return VerifyHashTag(preparedHash, sig)
|
||||
}
|
||||
|
||||
// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this
|
||||
// public key.
|
||||
func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) {
|
||||
h, err := keyRevocationHash(pk, sig.Hash)
|
||||
preparedHash, err := sig.PrepareVerify()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return pk.VerifySignature(h, sig)
|
||||
if err = keyRevocationHash(pk, preparedHash); err != nil {
|
||||
return err
|
||||
}
|
||||
return pk.VerifySignature(preparedHash, sig)
|
||||
}
|
||||
|
||||
// VerifySubkeyRevocationSignature returns nil iff sig is a valid subkey revocation signature,
|
||||
// made by this public key, of signed.
|
||||
func (pk *PublicKey) VerifySubkeyRevocationSignature(sig *Signature, signed *PublicKey) (err error) {
|
||||
h, err := keySignatureHash(pk, signed, sig.Hash)
|
||||
preparedHash, err := sig.PrepareVerify()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h, err := keySignatureHash(pk, signed, preparedHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -727,15 +978,15 @@ func (pk *PublicKey) VerifySubkeyRevocationSignature(sig *Signature, signed *Pub
|
||||
|
||||
// userIdSignatureHash returns a Hash of the message that needs to be signed
|
||||
// to assert that pk is a valid key for id.
|
||||
func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
|
||||
if !hashFunc.Available() {
|
||||
return nil, errors.UnsupportedError("hash function")
|
||||
}
|
||||
h = hashFunc.New()
|
||||
func userIdSignatureHash(id string, pk *PublicKey, h hash.Hash) (err error) {
|
||||
|
||||
// RFC 4880, section 5.2.4
|
||||
pk.SerializeSignaturePrefix(h)
|
||||
pk.serializeWithoutHeaders(h)
|
||||
if err := pk.SerializeSignaturePrefix(h); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := pk.serializeWithoutHeaders(h); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var buf [5]byte
|
||||
buf[0] = 0xb4
|
||||
@@ -746,28 +997,68 @@ func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash
|
||||
h.Write(buf[:])
|
||||
h.Write([]byte(id))
|
||||
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// directKeySignatureHash returns a Hash of the message that needs to be signed.
|
||||
func directKeySignatureHash(pk *PublicKey, h hash.Hash) (err error) {
|
||||
return pk.SerializeForHash(h)
|
||||
}
|
||||
|
||||
// VerifyUserIdHashTag returns nil iff sig appears to be a plausible signature over this
|
||||
// public key and UserId, based solely on its HashTag
|
||||
func (pk *PublicKey) VerifyUserIdHashTag(id string, sig *Signature) (err error) {
|
||||
preparedHash, err := sig.PrepareVerify()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = userIdSignatureHash(id, pk, preparedHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return VerifyHashTag(preparedHash, sig)
|
||||
}
|
||||
|
||||
// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
|
||||
// public key, that id is the identity of pub.
|
||||
func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) {
|
||||
h, err := userIdSignatureHash(id, pub, sig.Hash)
|
||||
h, err := sig.PrepareVerify()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := userIdSignatureHash(id, pub, h); err != nil {
|
||||
return err
|
||||
}
|
||||
return pk.VerifySignature(h, sig)
|
||||
}
|
||||
|
||||
// VerifyDirectKeySignature returns nil iff sig is a valid signature, made by this
|
||||
// public key.
|
||||
func (pk *PublicKey) VerifyDirectKeySignature(sig *Signature) (err error) {
|
||||
h, err := sig.PrepareVerify()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := directKeySignatureHash(pk, h); err != nil {
|
||||
return err
|
||||
}
|
||||
return pk.VerifySignature(h, sig)
|
||||
}
|
||||
|
||||
// KeyIdString returns the public key's fingerprint in capital hex
|
||||
// (e.g. "6C7EE1B8621CC013").
|
||||
func (pk *PublicKey) KeyIdString() string {
|
||||
return fmt.Sprintf("%X", pk.Fingerprint[12:20])
|
||||
return fmt.Sprintf("%016X", pk.KeyId)
|
||||
}
|
||||
|
||||
// KeyIdShortString returns the short form of public key's fingerprint
|
||||
// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
|
||||
// This function will return the full key id for v5 and v6 keys
|
||||
// since the short key id is undefined for them.
|
||||
func (pk *PublicKey) KeyIdShortString() string {
|
||||
if pk.Version >= 5 {
|
||||
return pk.KeyIdString()
|
||||
}
|
||||
return fmt.Sprintf("%X", pk.Fingerprint[16:20])
|
||||
}
|
||||
|
||||
@@ -786,21 +1077,49 @@ func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
|
||||
bitLength = pk.p.BitLength()
|
||||
case PubKeyAlgoEdDSA:
|
||||
bitLength = pk.p.BitLength()
|
||||
case PubKeyAlgoX25519:
|
||||
bitLength = x25519.KeySize * 8
|
||||
case PubKeyAlgoX448:
|
||||
bitLength = x448.KeySize * 8
|
||||
case PubKeyAlgoEd25519:
|
||||
bitLength = ed25519.PublicKeySize * 8
|
||||
case PubKeyAlgoEd448:
|
||||
bitLength = ed448.PublicKeySize * 8
|
||||
default:
|
||||
err = errors.InvalidArgumentError("bad public-key algorithm")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Curve returns the used elliptic curve of this public key.
|
||||
// Returns an error if no elliptic curve is used.
|
||||
func (pk *PublicKey) Curve() (curve Curve, err error) {
|
||||
switch pk.PubKeyAlgo {
|
||||
case PubKeyAlgoECDSA, PubKeyAlgoECDH, PubKeyAlgoEdDSA:
|
||||
curveInfo := ecc.FindByOid(pk.oid)
|
||||
if curveInfo == nil {
|
||||
return "", errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
|
||||
}
|
||||
curve = Curve(curveInfo.GenName)
|
||||
case PubKeyAlgoEd25519, PubKeyAlgoX25519:
|
||||
curve = Curve25519
|
||||
case PubKeyAlgoEd448, PubKeyAlgoX448:
|
||||
curve = Curve448
|
||||
default:
|
||||
err = errors.InvalidArgumentError("public key does not operate with an elliptic curve")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// KeyExpired returns whether sig is a self-signature of a key that has
|
||||
// expired or is created in the future.
|
||||
func (pk *PublicKey) KeyExpired(sig *Signature, currentTime time.Time) bool {
|
||||
if pk.CreationTime.After(currentTime) {
|
||||
if pk.CreationTime.Unix() > currentTime.Unix() {
|
||||
return true
|
||||
}
|
||||
if sig.KeyLifetimeSecs == nil || *sig.KeyLifetimeSecs == 0 {
|
||||
return false
|
||||
}
|
||||
expiry := pk.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
|
||||
return currentTime.After(expiry)
|
||||
return currentTime.Unix() > expiry.Unix()
|
||||
}
|
||||
|
||||
155
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go
generated
vendored
155
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go
generated
vendored
@@ -10,6 +10,12 @@ import (
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
type PacketReader interface {
|
||||
Next() (p Packet, err error)
|
||||
Push(reader io.Reader) (err error)
|
||||
Unread(p Packet)
|
||||
}
|
||||
|
||||
// Reader reads packets from an io.Reader and allows packets to be 'unread' so
|
||||
// that they result from the next call to Next.
|
||||
type Reader struct {
|
||||
@@ -26,24 +32,13 @@ type Reader struct {
|
||||
const maxReaders = 32
|
||||
|
||||
// Next returns the most recently unread Packet, or reads another packet from
|
||||
// the top-most io.Reader. Unknown packet types are skipped.
|
||||
// the top-most io.Reader. Unknown/unsupported/Marker packet types are skipped.
|
||||
func (r *Reader) Next() (p Packet, err error) {
|
||||
if len(r.q) > 0 {
|
||||
p = r.q[len(r.q)-1]
|
||||
r.q = r.q[:len(r.q)-1]
|
||||
return
|
||||
}
|
||||
|
||||
for len(r.readers) > 0 {
|
||||
p, err = Read(r.readers[len(r.readers)-1])
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
for {
|
||||
p, err := r.read()
|
||||
if err == io.EOF {
|
||||
r.readers = r.readers[:len(r.readers)-1]
|
||||
continue
|
||||
}
|
||||
// TODO: Add strict mode that rejects unknown packets, instead of ignoring them.
|
||||
break
|
||||
} else if err != nil {
|
||||
if _, ok := err.(errors.UnknownPacketTypeError); ok {
|
||||
continue
|
||||
}
|
||||
@@ -55,8 +50,63 @@ func (r *Reader) Next() (p Packet, err error) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
} else {
|
||||
//A marker packet MUST be ignored when received
|
||||
switch p.(type) {
|
||||
case *Marker:
|
||||
continue
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
}
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
// Next returns the most recently unread Packet, or reads another packet from
|
||||
// the top-most io.Reader. Unknown/Marker packet types are skipped while unsupported
|
||||
// packets are returned as UnsupportedPacket type.
|
||||
func (r *Reader) NextWithUnsupported() (p Packet, err error) {
|
||||
for {
|
||||
p, err = r.read()
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
if _, ok := err.(errors.UnknownPacketTypeError); ok {
|
||||
continue
|
||||
}
|
||||
if casteErr, ok := err.(errors.UnsupportedError); ok {
|
||||
return &UnsupportedPacket{
|
||||
IncompletePacket: p,
|
||||
Error: casteErr,
|
||||
}, nil
|
||||
}
|
||||
return
|
||||
} else {
|
||||
//A marker packet MUST be ignored when received
|
||||
switch p.(type) {
|
||||
case *Marker:
|
||||
continue
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
func (r *Reader) read() (p Packet, err error) {
|
||||
if len(r.q) > 0 {
|
||||
p = r.q[len(r.q)-1]
|
||||
r.q = r.q[:len(r.q)-1]
|
||||
return
|
||||
}
|
||||
for len(r.readers) > 0 {
|
||||
p, err = Read(r.readers[len(r.readers)-1])
|
||||
if err == io.EOF {
|
||||
r.readers = r.readers[:len(r.readers)-1]
|
||||
continue
|
||||
}
|
||||
return p, err
|
||||
}
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
@@ -84,3 +134,76 @@ func NewReader(r io.Reader) *Reader {
|
||||
readers: []io.Reader{r},
|
||||
}
|
||||
}
|
||||
|
||||
// CheckReader is similar to Reader but additionally
|
||||
// uses the pushdown automata to verify the read packet sequence.
|
||||
type CheckReader struct {
|
||||
Reader
|
||||
verifier *SequenceVerifier
|
||||
fullyRead bool
|
||||
}
|
||||
|
||||
// Next returns the most recently unread Packet, or reads another packet from
|
||||
// the top-most io.Reader. Unknown packet types are skipped.
|
||||
// If the read packet sequence does not conform to the packet composition
|
||||
// rules in rfc4880, it returns an error.
|
||||
func (r *CheckReader) Next() (p Packet, err error) {
|
||||
if r.fullyRead {
|
||||
return nil, io.EOF
|
||||
}
|
||||
if len(r.q) > 0 {
|
||||
p = r.q[len(r.q)-1]
|
||||
r.q = r.q[:len(r.q)-1]
|
||||
return
|
||||
}
|
||||
var errMsg error
|
||||
for len(r.readers) > 0 {
|
||||
p, errMsg, err = ReadWithCheck(r.readers[len(r.readers)-1], r.verifier)
|
||||
if errMsg != nil {
|
||||
err = errMsg
|
||||
return
|
||||
}
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
if err == io.EOF {
|
||||
r.readers = r.readers[:len(r.readers)-1]
|
||||
continue
|
||||
}
|
||||
//A marker packet MUST be ignored when received
|
||||
switch p.(type) {
|
||||
case *Marker:
|
||||
continue
|
||||
}
|
||||
if _, ok := err.(errors.UnknownPacketTypeError); ok {
|
||||
continue
|
||||
}
|
||||
if _, ok := err.(errors.UnsupportedError); ok {
|
||||
switch p.(type) {
|
||||
case *SymmetricallyEncrypted, *AEADEncrypted, *Compressed, *LiteralData:
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if errMsg = r.verifier.Next(EOSSymbol); errMsg != nil {
|
||||
return nil, errMsg
|
||||
}
|
||||
if errMsg = r.verifier.AssertValid(); errMsg != nil {
|
||||
return nil, errMsg
|
||||
}
|
||||
r.fullyRead = true
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
func NewCheckReader(r io.Reader) *CheckReader {
|
||||
return &CheckReader{
|
||||
Reader: Reader{
|
||||
q: nil,
|
||||
readers: []io.Reader{r},
|
||||
},
|
||||
verifier: NewSequenceVerifier(),
|
||||
fullyRead: false,
|
||||
}
|
||||
}
|
||||
|
||||
15
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/recipient.go
generated
vendored
Normal file
15
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/recipient.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
package packet
|
||||
|
||||
// Recipient type represents a Intended Recipient Fingerprint subpacket
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh#name-intended-recipient-fingerpr
|
||||
type Recipient struct {
|
||||
KeyVersion int
|
||||
Fingerprint []byte
|
||||
}
|
||||
|
||||
func (r *Recipient) Serialize() []byte {
|
||||
packet := make([]byte, len(r.Fingerprint)+1)
|
||||
packet[0] = byte(r.KeyVersion)
|
||||
copy(packet[1:], r.Fingerprint)
|
||||
return packet
|
||||
}
|
||||
735
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go
generated
vendored
735
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go
generated
vendored
File diff suppressed because it is too large
Load Diff
89
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go
generated
vendored
89
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go
generated
vendored
@@ -7,11 +7,13 @@ package packet
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"crypto/sha256"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
)
|
||||
|
||||
// This is the largest session key that we'll support. Since at most 256-bit cipher
|
||||
@@ -39,10 +41,21 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
|
||||
return err
|
||||
}
|
||||
ske.Version = int(buf[0])
|
||||
if ske.Version != 4 && ske.Version != 5 {
|
||||
if ske.Version != 4 && ske.Version != 5 && ske.Version != 6 {
|
||||
return errors.UnsupportedError("unknown SymmetricKeyEncrypted version")
|
||||
}
|
||||
|
||||
if V5Disabled && ske.Version == 5 {
|
||||
return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed")
|
||||
}
|
||||
|
||||
if ske.Version > 5 {
|
||||
// Scalar octet count
|
||||
if _, err := readFull(r, buf[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Cipher function
|
||||
if _, err := readFull(r, buf[:]); err != nil {
|
||||
return err
|
||||
@@ -52,7 +65,7 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
|
||||
return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[0])))
|
||||
}
|
||||
|
||||
if ske.Version == 5 {
|
||||
if ske.Version >= 5 {
|
||||
// AEAD mode
|
||||
if _, err := readFull(r, buf[:]); err != nil {
|
||||
return errors.StructuralError("cannot read AEAD octet from packet")
|
||||
@@ -60,6 +73,13 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
|
||||
ske.Mode = AEADMode(buf[0])
|
||||
}
|
||||
|
||||
if ske.Version > 5 {
|
||||
// Scalar octet count
|
||||
if _, err := readFull(r, buf[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
if ske.s2k, err = s2k.Parse(r); err != nil {
|
||||
if _, ok := err.(errors.ErrDummyPrivateKey); ok {
|
||||
@@ -68,7 +88,7 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if ske.Version == 5 {
|
||||
if ske.Version >= 5 {
|
||||
// AEAD IV
|
||||
iv := make([]byte, ske.Mode.IvLength())
|
||||
_, err := readFull(r, iv)
|
||||
@@ -109,8 +129,8 @@ func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunc
|
||||
case 4:
|
||||
plaintextKey, cipherFunc, err := ske.decryptV4(key)
|
||||
return plaintextKey, cipherFunc, err
|
||||
case 5:
|
||||
plaintextKey, err := ske.decryptV5(key)
|
||||
case 5, 6:
|
||||
plaintextKey, err := ske.aeadDecrypt(ske.Version, key)
|
||||
return plaintextKey, CipherFunction(0), err
|
||||
}
|
||||
err := errors.UnsupportedError("unknown SymmetricKeyEncrypted version")
|
||||
@@ -136,9 +156,9 @@ func (ske *SymmetricKeyEncrypted) decryptV4(key []byte) ([]byte, CipherFunction,
|
||||
return plaintextKey, cipherFunc, nil
|
||||
}
|
||||
|
||||
func (ske *SymmetricKeyEncrypted) decryptV5(key []byte) ([]byte, error) {
|
||||
adata := []byte{0xc3, byte(5), byte(ske.CipherFunc), byte(ske.Mode)}
|
||||
aead := getEncryptedKeyAeadInstance(ske.CipherFunc, ske.Mode, key, adata)
|
||||
func (ske *SymmetricKeyEncrypted) aeadDecrypt(version int, key []byte) ([]byte, error) {
|
||||
adata := []byte{0xc3, byte(version), byte(ske.CipherFunc), byte(ske.Mode)}
|
||||
aead := getEncryptedKeyAeadInstance(ske.CipherFunc, ske.Mode, key, adata, version)
|
||||
|
||||
plaintextKey, err := aead.Open(nil, ske.iv, ske.encryptedKey, adata)
|
||||
if err != nil {
|
||||
@@ -175,10 +195,22 @@ func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Conf
|
||||
// the given passphrase. The returned session key must be passed to
|
||||
// SerializeSymmetricallyEncrypted.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
// Deprecated: Use SerializeSymmetricKeyEncryptedAEADReuseKey instead.
|
||||
func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, passphrase []byte, config *Config) (err error) {
|
||||
return SerializeSymmetricKeyEncryptedAEADReuseKey(w, sessionKey, passphrase, config.AEAD() != nil, config)
|
||||
}
|
||||
|
||||
// SerializeSymmetricKeyEncryptedAEADReuseKey serializes a symmetric key packet to w.
|
||||
// The packet contains the given session key, encrypted by a key derived from
|
||||
// the given passphrase. The returned session key must be passed to
|
||||
// SerializeSymmetricallyEncrypted.
|
||||
// If aeadSupported is set, SKESK v6 is used, otherwise v4.
|
||||
// Note: aeadSupported MUST match the value passed to SerializeSymmetricallyEncrypted.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func SerializeSymmetricKeyEncryptedAEADReuseKey(w io.Writer, sessionKey []byte, passphrase []byte, aeadSupported bool, config *Config) (err error) {
|
||||
var version int
|
||||
if config.AEAD() != nil {
|
||||
version = 5
|
||||
if aeadSupported {
|
||||
version = 6
|
||||
} else {
|
||||
version = 4
|
||||
}
|
||||
@@ -203,11 +235,15 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass
|
||||
switch version {
|
||||
case 4:
|
||||
packetLength = 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
|
||||
case 5:
|
||||
case 5, 6:
|
||||
ivLen := config.AEAD().Mode().IvLength()
|
||||
tagLen := config.AEAD().Mode().TagLength()
|
||||
packetLength = 3 + len(s2kBytes) + ivLen + keySize + tagLen
|
||||
}
|
||||
if version > 5 {
|
||||
packetLength += 2 // additional octet count fields
|
||||
}
|
||||
|
||||
err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -216,13 +252,22 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass
|
||||
// Symmetric Key Encrypted Version
|
||||
buf := []byte{byte(version)}
|
||||
|
||||
if version > 5 {
|
||||
// Scalar octet count
|
||||
buf = append(buf, byte(3+len(s2kBytes)+config.AEAD().Mode().IvLength()))
|
||||
}
|
||||
|
||||
// Cipher function
|
||||
buf = append(buf, byte(cipherFunc))
|
||||
|
||||
if version == 5 {
|
||||
if version >= 5 {
|
||||
// AEAD mode
|
||||
buf = append(buf, byte(config.AEAD().Mode()))
|
||||
}
|
||||
if version > 5 {
|
||||
// Scalar octet count
|
||||
buf = append(buf, byte(len(s2kBytes)))
|
||||
}
|
||||
_, err = w.Write(buf)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -243,10 +288,10 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case 5:
|
||||
case 5, 6:
|
||||
mode := config.AEAD().Mode()
|
||||
adata := []byte{0xc3, byte(5), byte(cipherFunc), byte(mode)}
|
||||
aead := getEncryptedKeyAeadInstance(cipherFunc, mode, keyEncryptingKey, adata)
|
||||
adata := []byte{0xc3, byte(version), byte(cipherFunc), byte(mode)}
|
||||
aead := getEncryptedKeyAeadInstance(cipherFunc, mode, keyEncryptingKey, adata, version)
|
||||
|
||||
// Sample iv using random reader
|
||||
iv := make([]byte, config.AEAD().Mode().IvLength())
|
||||
@@ -270,7 +315,17 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass
|
||||
return
|
||||
}
|
||||
|
||||
func getEncryptedKeyAeadInstance(c CipherFunction, mode AEADMode, inputKey, associatedData []byte) (aead cipher.AEAD) {
|
||||
blockCipher := c.new(inputKey)
|
||||
func getEncryptedKeyAeadInstance(c CipherFunction, mode AEADMode, inputKey, associatedData []byte, version int) (aead cipher.AEAD) {
|
||||
var blockCipher cipher.Block
|
||||
if version > 5 {
|
||||
hkdfReader := hkdf.New(sha256.New, inputKey, []byte{}, associatedData)
|
||||
|
||||
encryptionKey := make([]byte, c.KeySize())
|
||||
_, _ = readFull(hkdfReader, encryptionKey)
|
||||
|
||||
blockCipher = c.new(encryptionKey)
|
||||
} else {
|
||||
blockCipher = c.new(inputKey)
|
||||
}
|
||||
return mode.new(blockCipher)
|
||||
}
|
||||
|
||||
4
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go
generated
vendored
4
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go
generated
vendored
@@ -74,6 +74,10 @@ func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.Read
|
||||
// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
|
||||
// to w and returns a WriteCloser to which the to-be-encrypted packets can be
|
||||
// written.
|
||||
// If aeadSupported is set to true, SEIPDv2 is used with the indicated CipherSuite.
|
||||
// Otherwise, SEIPDv1 is used with the indicated CipherFunction.
|
||||
// Note: aeadSupported MUST match the value passed to SerializeEncryptedKeyAEAD
|
||||
// and/or SerializeSymmetricKeyEncryptedAEADReuseKey.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, aeadSupported bool, cipherSuite CipherSuite, key []byte, config *Config) (Contents io.WriteCloser, err error) {
|
||||
writeCloser := noOpCloser{w}
|
||||
|
||||
40
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go
generated
vendored
40
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go
generated
vendored
@@ -7,7 +7,9 @@ package packet
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
@@ -25,19 +27,19 @@ func (se *SymmetricallyEncrypted) parseAead(r io.Reader) error {
|
||||
se.Cipher = CipherFunction(headerData[0])
|
||||
// cipherFunc must have block size 16 to use AEAD
|
||||
if se.Cipher.blockSize() != 16 {
|
||||
return errors.UnsupportedError("invalid aead cipher: " + string(se.Cipher))
|
||||
return errors.UnsupportedError("invalid aead cipher: " + strconv.Itoa(int(se.Cipher)))
|
||||
}
|
||||
|
||||
// Mode
|
||||
se.Mode = AEADMode(headerData[1])
|
||||
if se.Mode.TagLength() == 0 {
|
||||
return errors.UnsupportedError("unknown aead mode: " + string(se.Mode))
|
||||
return errors.UnsupportedError("unknown aead mode: " + strconv.Itoa(int(se.Mode)))
|
||||
}
|
||||
|
||||
// Chunk size
|
||||
se.ChunkSizeByte = headerData[2]
|
||||
if se.ChunkSizeByte > 16 {
|
||||
return errors.UnsupportedError("invalid aead chunk size byte: " + string(se.ChunkSizeByte))
|
||||
return errors.UnsupportedError("invalid aead chunk size byte: " + strconv.Itoa(int(se.ChunkSizeByte)))
|
||||
}
|
||||
|
||||
// Salt
|
||||
@@ -62,11 +64,16 @@ func (se *SymmetricallyEncrypted) associatedData() []byte {
|
||||
// decryptAead decrypts a V2 SEIPD packet (AEAD) as specified in
|
||||
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2
|
||||
func (se *SymmetricallyEncrypted) decryptAead(inputKey []byte) (io.ReadCloser, error) {
|
||||
aead, nonce := getSymmetricallyEncryptedAeadInstance(se.Cipher, se.Mode, inputKey, se.Salt[:], se.associatedData())
|
||||
if se.Cipher.KeySize() != len(inputKey) {
|
||||
return nil, errors.StructuralError(fmt.Sprintf("invalid session key length for cipher: got %d bytes, but expected %d bytes", len(inputKey), se.Cipher.KeySize()))
|
||||
}
|
||||
|
||||
aead, nonce := getSymmetricallyEncryptedAeadInstance(se.Cipher, se.Mode, inputKey, se.Salt[:], se.associatedData())
|
||||
// Carry the first tagLen bytes
|
||||
chunkSize := decodeAEADChunkSize(se.ChunkSizeByte)
|
||||
tagLen := se.Mode.TagLength()
|
||||
peekedBytes := make([]byte, tagLen)
|
||||
chunkBytes := make([]byte, chunkSize+tagLen*2)
|
||||
peekedBytes := chunkBytes[chunkSize+tagLen:]
|
||||
n, err := io.ReadFull(se.Contents, peekedBytes)
|
||||
if n < tagLen || (err != nil && err != io.EOF) {
|
||||
return nil, errors.StructuralError("not enough data to decrypt:" + err.Error())
|
||||
@@ -76,12 +83,13 @@ func (se *SymmetricallyEncrypted) decryptAead(inputKey []byte) (io.ReadCloser, e
|
||||
aeadCrypter: aeadCrypter{
|
||||
aead: aead,
|
||||
chunkSize: decodeAEADChunkSize(se.ChunkSizeByte),
|
||||
initialNonce: nonce,
|
||||
nonce: nonce,
|
||||
associatedData: se.associatedData(),
|
||||
chunkIndex: make([]byte, 8),
|
||||
chunkIndex: nonce[len(nonce)-8:],
|
||||
packetTag: packetTypeSymmetricallyEncryptedIntegrityProtected,
|
||||
},
|
||||
reader: se.Contents,
|
||||
chunkBytes: chunkBytes,
|
||||
peekedBytes: peekedBytes,
|
||||
}, nil
|
||||
}
|
||||
@@ -115,7 +123,7 @@ func serializeSymmetricallyEncryptedAead(ciphertext io.WriteCloser, cipherSuite
|
||||
|
||||
// Random salt
|
||||
salt := make([]byte, aeadSaltSize)
|
||||
if _, err := rand.Read(salt); err != nil {
|
||||
if _, err := io.ReadFull(rand, salt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -125,16 +133,20 @@ func serializeSymmetricallyEncryptedAead(ciphertext io.WriteCloser, cipherSuite
|
||||
|
||||
aead, nonce := getSymmetricallyEncryptedAeadInstance(cipherSuite.Cipher, cipherSuite.Mode, inputKey, salt, prefix)
|
||||
|
||||
chunkSize := decodeAEADChunkSize(chunkSizeByte)
|
||||
tagLen := aead.Overhead()
|
||||
chunkBytes := make([]byte, chunkSize+tagLen)
|
||||
return &aeadEncrypter{
|
||||
aeadCrypter: aeadCrypter{
|
||||
aead: aead,
|
||||
chunkSize: decodeAEADChunkSize(chunkSizeByte),
|
||||
chunkSize: chunkSize,
|
||||
associatedData: prefix,
|
||||
chunkIndex: make([]byte, 8),
|
||||
initialNonce: nonce,
|
||||
nonce: nonce,
|
||||
chunkIndex: nonce[len(nonce)-8:],
|
||||
packetTag: packetTypeSymmetricallyEncryptedIntegrityProtected,
|
||||
},
|
||||
writer: ciphertext,
|
||||
chunkBytes: chunkBytes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -144,10 +156,10 @@ func getSymmetricallyEncryptedAeadInstance(c CipherFunction, mode AEADMode, inpu
|
||||
encryptionKey := make([]byte, c.KeySize())
|
||||
_, _ = readFull(hkdfReader, encryptionKey)
|
||||
|
||||
// Last 64 bits of nonce are the counter
|
||||
nonce = make([]byte, mode.IvLength()-8)
|
||||
nonce = make([]byte, mode.IvLength())
|
||||
|
||||
_, _ = readFull(hkdfReader, nonce)
|
||||
// Last 64 bits of nonce are the counter
|
||||
_, _ = readFull(hkdfReader, nonce[:len(nonce)-8])
|
||||
|
||||
blockCipher := c.new(encryptionKey)
|
||||
aead = mode.new(blockCipher)
|
||||
|
||||
10
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_mdc.go
generated
vendored
10
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_mdc.go
generated
vendored
@@ -148,7 +148,7 @@ const mdcPacketTagByte = byte(0x80) | 0x40 | 19
|
||||
|
||||
func (ser *seMDCReader) Close() error {
|
||||
if ser.error {
|
||||
return errors.ErrMDCMissing
|
||||
return errors.ErrMDCHashMismatch
|
||||
}
|
||||
|
||||
for !ser.eof {
|
||||
@@ -159,7 +159,7 @@ func (ser *seMDCReader) Close() error {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return errors.ErrMDCMissing
|
||||
return errors.ErrMDCHashMismatch
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ func (ser *seMDCReader) Close() error {
|
||||
// The hash already includes the MDC header, but we still check its value
|
||||
// to confirm encryption correctness
|
||||
if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
|
||||
return errors.ErrMDCMissing
|
||||
return errors.ErrMDCHashMismatch
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -237,9 +237,9 @@ func serializeSymmetricallyEncryptedMdc(ciphertext io.WriteCloser, c CipherFunct
|
||||
block := c.new(key)
|
||||
blockSize := block.BlockSize()
|
||||
iv := make([]byte, blockSize)
|
||||
_, err = config.Random().Read(iv)
|
||||
_, err = io.ReadFull(config.Random(), iv)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync)
|
||||
_, err = ciphertext.Write(prefix)
|
||||
|
||||
3
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go
generated
vendored
3
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go
generated
vendored
@@ -9,7 +9,6 @@ import (
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
const UserAttrImageSubpacket = 1
|
||||
@@ -63,7 +62,7 @@ func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute {
|
||||
|
||||
func (uat *UserAttribute) parse(r io.Reader) (err error) {
|
||||
// RFC 4880, section 5.13
|
||||
b, err := ioutil.ReadAll(r)
|
||||
b, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
3
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userid.go
generated
vendored
3
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userid.go
generated
vendored
@@ -6,7 +6,6 @@ package packet
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -66,7 +65,7 @@ func NewUserId(name, comment, email string) *UserId {
|
||||
|
||||
func (uid *UserId) parse(r io.Reader) (err error) {
|
||||
// RFC 4880, section 5.11
|
||||
b, err := ioutil.ReadAll(r)
|
||||
b, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
111
vendor/github.com/ProtonMail/go-crypto/openpgp/read.go
generated
vendored
111
vendor/github.com/ProtonMail/go-crypto/openpgp/read.go
generated
vendored
@@ -46,6 +46,7 @@ type MessageDetails struct {
|
||||
DecryptedWith Key // the private key used to decrypt the message, if any.
|
||||
IsSigned bool // true if the message is signed.
|
||||
SignedByKeyId uint64 // the key id of the signer, if any.
|
||||
SignedByFingerprint []byte // the key fingerprint of the signer, if any.
|
||||
SignedBy *Key // the key of the signer, if available.
|
||||
LiteralData *packet.LiteralData // the metadata of the contents
|
||||
UnverifiedBody io.Reader // the contents of the message.
|
||||
@@ -117,7 +118,7 @@ ParsePackets:
|
||||
// This packet contains the decryption key encrypted to a public key.
|
||||
md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
|
||||
switch p.Algo {
|
||||
case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal, packet.PubKeyAlgoECDH:
|
||||
case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal, packet.PubKeyAlgoECDH, packet.PubKeyAlgoX25519, packet.PubKeyAlgoX448:
|
||||
break
|
||||
default:
|
||||
continue
|
||||
@@ -232,7 +233,7 @@ FindKey:
|
||||
}
|
||||
mdFinal, sensitiveParsingErr := readSignedMessage(packets, md, keyring, config)
|
||||
if sensitiveParsingErr != nil {
|
||||
return nil, errors.StructuralError("parsing error")
|
||||
return nil, errors.HandleSensitiveParsingError(sensitiveParsingErr, md.decrypted != nil)
|
||||
}
|
||||
return mdFinal, nil
|
||||
}
|
||||
@@ -258,7 +259,7 @@ FindLiteralData:
|
||||
}
|
||||
switch p := p.(type) {
|
||||
case *packet.Compressed:
|
||||
if err := packets.Push(p.Body); err != nil {
|
||||
if err := packets.Push(p.LimitedBodyReader(config.DecompressedMessageSizeLimit())); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case *packet.OnePassSignature:
|
||||
@@ -270,13 +271,17 @@ FindLiteralData:
|
||||
prevLast = true
|
||||
}
|
||||
|
||||
h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
|
||||
h, wrappedHash, err = hashForSignature(p.Hash, p.SigType, p.Salt)
|
||||
if err != nil {
|
||||
md.SignatureError = err
|
||||
}
|
||||
|
||||
md.IsSigned = true
|
||||
if p.Version == 6 {
|
||||
md.SignedByFingerprint = p.KeyFingerprint
|
||||
}
|
||||
md.SignedByKeyId = p.KeyId
|
||||
|
||||
if keyring != nil {
|
||||
keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign)
|
||||
if len(keys) > 0 {
|
||||
@@ -292,7 +297,7 @@ FindLiteralData:
|
||||
if md.IsSigned && md.SignatureError == nil {
|
||||
md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md, config}
|
||||
} else if md.decrypted != nil {
|
||||
md.UnverifiedBody = checkReader{md}
|
||||
md.UnverifiedBody = &checkReader{md, false}
|
||||
} else {
|
||||
md.UnverifiedBody = md.LiteralData.Body
|
||||
}
|
||||
@@ -300,12 +305,22 @@ FindLiteralData:
|
||||
return md, nil
|
||||
}
|
||||
|
||||
func wrapHashForSignature(hashFunc hash.Hash, sigType packet.SignatureType) (hash.Hash, error) {
|
||||
switch sigType {
|
||||
case packet.SigTypeBinary:
|
||||
return hashFunc, nil
|
||||
case packet.SigTypeText:
|
||||
return NewCanonicalTextHash(hashFunc), nil
|
||||
}
|
||||
return nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
|
||||
}
|
||||
|
||||
// hashForSignature returns a pair of hashes that can be used to verify a
|
||||
// signature. The signature may specify that the contents of the signed message
|
||||
// should be preprocessed (i.e. to normalize line endings). Thus this function
|
||||
// returns two hashes. The second should be used to hash the message itself and
|
||||
// performs any needed preprocessing.
|
||||
func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
|
||||
func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType, sigSalt []byte) (hash.Hash, hash.Hash, error) {
|
||||
if _, ok := algorithm.HashToHashIdWithSha1(hashFunc); !ok {
|
||||
return nil, nil, errors.UnsupportedError("unsupported hash function")
|
||||
}
|
||||
@@ -313,14 +328,19 @@ func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType) (hash.
|
||||
return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashFunc)))
|
||||
}
|
||||
h := hashFunc.New()
|
||||
|
||||
if sigSalt != nil {
|
||||
h.Write(sigSalt)
|
||||
}
|
||||
wrappedHash, err := wrapHashForSignature(h, sigType)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
switch sigType {
|
||||
case packet.SigTypeBinary:
|
||||
return h, h, nil
|
||||
return h, wrappedHash, nil
|
||||
case packet.SigTypeText:
|
||||
return h, NewCanonicalTextHash(h), nil
|
||||
return h, wrappedHash, nil
|
||||
}
|
||||
|
||||
return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
|
||||
}
|
||||
|
||||
@@ -329,20 +349,26 @@ func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType) (hash.
|
||||
// MDC checks.
|
||||
type checkReader struct {
|
||||
md *MessageDetails
|
||||
checked bool
|
||||
}
|
||||
|
||||
func (cr checkReader) Read(buf []byte) (int, error) {
|
||||
func (cr *checkReader) Read(buf []byte) (int, error) {
|
||||
n, sensitiveParsingError := cr.md.LiteralData.Body.Read(buf)
|
||||
if sensitiveParsingError == io.EOF {
|
||||
if cr.checked {
|
||||
// Only check once
|
||||
return n, io.EOF
|
||||
}
|
||||
mdcErr := cr.md.decrypted.Close()
|
||||
if mdcErr != nil {
|
||||
return n, mdcErr
|
||||
}
|
||||
cr.checked = true
|
||||
return n, io.EOF
|
||||
}
|
||||
|
||||
if sensitiveParsingError != nil {
|
||||
return n, errors.StructuralError("parsing error")
|
||||
return n, errors.HandleSensitiveParsingError(sensitiveParsingError, true)
|
||||
}
|
||||
|
||||
return n, nil
|
||||
@@ -366,6 +392,7 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
|
||||
scr.wrappedHash.Write(buf[:n])
|
||||
}
|
||||
|
||||
readsDecryptedData := scr.md.decrypted != nil
|
||||
if sensitiveParsingError == io.EOF {
|
||||
var p packet.Packet
|
||||
var readError error
|
||||
@@ -384,7 +411,7 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
|
||||
key := scr.md.SignedBy
|
||||
signatureError := key.PublicKey.VerifySignature(scr.h, sig)
|
||||
if signatureError == nil {
|
||||
signatureError = checkSignatureDetails(key, sig, scr.config)
|
||||
signatureError = checkMessageSignatureDetails(key, sig, scr.config)
|
||||
}
|
||||
scr.md.Signature = sig
|
||||
scr.md.SignatureError = signatureError
|
||||
@@ -408,16 +435,15 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
|
||||
// unsigned hash of its own. In order to check this we need to
|
||||
// close that Reader.
|
||||
if scr.md.decrypted != nil {
|
||||
mdcErr := scr.md.decrypted.Close()
|
||||
if mdcErr != nil {
|
||||
return n, mdcErr
|
||||
if sensitiveParsingError := scr.md.decrypted.Close(); sensitiveParsingError != nil {
|
||||
return n, errors.HandleSensitiveParsingError(sensitiveParsingError, true)
|
||||
}
|
||||
}
|
||||
return n, io.EOF
|
||||
}
|
||||
|
||||
if sensitiveParsingError != nil {
|
||||
return n, errors.StructuralError("parsing error")
|
||||
return n, errors.HandleSensitiveParsingError(sensitiveParsingError, readsDecryptedData)
|
||||
}
|
||||
|
||||
return n, nil
|
||||
@@ -428,14 +454,13 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
|
||||
// if any, and a possible signature verification error.
|
||||
// If the signer isn't known, ErrUnknownIssuer is returned.
|
||||
func VerifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
|
||||
var expectedHashes []crypto.Hash
|
||||
return verifyDetachedSignature(keyring, signed, signature, expectedHashes, config)
|
||||
return verifyDetachedSignature(keyring, signed, signature, nil, false, config)
|
||||
}
|
||||
|
||||
// VerifyDetachedSignatureAndHash performs the same actions as
|
||||
// VerifyDetachedSignature and checks that the expected hash functions were used.
|
||||
func VerifyDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
|
||||
return verifyDetachedSignature(keyring, signed, signature, expectedHashes, config)
|
||||
return verifyDetachedSignature(keyring, signed, signature, expectedHashes, true, config)
|
||||
}
|
||||
|
||||
// CheckDetachedSignature takes a signed file and a detached signature and
|
||||
@@ -443,25 +468,24 @@ func VerifyDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader
|
||||
// signature verification error. If the signer isn't known,
|
||||
// ErrUnknownIssuer is returned.
|
||||
func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) {
|
||||
var expectedHashes []crypto.Hash
|
||||
return CheckDetachedSignatureAndHash(keyring, signed, signature, expectedHashes, config)
|
||||
_, signer, err = verifyDetachedSignature(keyring, signed, signature, nil, false, config)
|
||||
return
|
||||
}
|
||||
|
||||
// CheckDetachedSignatureAndHash performs the same actions as
|
||||
// CheckDetachedSignature and checks that the expected hash functions were used.
|
||||
func CheckDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (signer *Entity, err error) {
|
||||
_, signer, err = verifyDetachedSignature(keyring, signed, signature, expectedHashes, config)
|
||||
_, signer, err = verifyDetachedSignature(keyring, signed, signature, expectedHashes, true, config)
|
||||
return
|
||||
}
|
||||
|
||||
func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
|
||||
func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, checkHashes bool, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
|
||||
var issuerKeyId uint64
|
||||
var hashFunc crypto.Hash
|
||||
var sigType packet.SignatureType
|
||||
var keys []Key
|
||||
var p packet.Packet
|
||||
|
||||
expectedHashesLen := len(expectedHashes)
|
||||
packets := packet.NewReader(signature)
|
||||
for {
|
||||
p, err = packets.Next()
|
||||
@@ -483,16 +507,19 @@ func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expec
|
||||
issuerKeyId = *sig.IssuerKeyId
|
||||
hashFunc = sig.Hash
|
||||
sigType = sig.SigType
|
||||
|
||||
for i, expectedHash := range expectedHashes {
|
||||
if checkHashes {
|
||||
matchFound := false
|
||||
// check for hashes
|
||||
for _, expectedHash := range expectedHashes {
|
||||
if hashFunc == expectedHash {
|
||||
matchFound = true
|
||||
break
|
||||
}
|
||||
if i+1 == expectedHashesLen {
|
||||
return nil, nil, errors.StructuralError("hash algorithm mismatch with cleartext message headers")
|
||||
}
|
||||
if !matchFound {
|
||||
return nil, nil, errors.StructuralError("hash algorithm or salt mismatch with cleartext message headers")
|
||||
}
|
||||
}
|
||||
|
||||
keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign)
|
||||
if len(keys) > 0 {
|
||||
break
|
||||
@@ -503,7 +530,11 @@ func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expec
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
h, wrappedHash, err := hashForSignature(hashFunc, sigType)
|
||||
h, err := sig.PrepareVerify()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
wrappedHash, err := wrapHashForSignature(h, sigType)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -515,7 +546,7 @@ func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expec
|
||||
for _, key := range keys {
|
||||
err = key.PublicKey.VerifySignature(h, sig)
|
||||
if err == nil {
|
||||
return sig, key.Entity, checkSignatureDetails(&key, sig, config)
|
||||
return sig, key.Entity, checkMessageSignatureDetails(&key, sig, config)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,7 +564,7 @@ func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader,
|
||||
return CheckDetachedSignature(keyring, signed, body, config)
|
||||
}
|
||||
|
||||
// checkSignatureDetails returns an error if:
|
||||
// checkMessageSignatureDetails returns an error if:
|
||||
// - The signature (or one of the binding signatures mentioned below)
|
||||
// has a unknown critical notation data subpacket
|
||||
// - The primary key of the signing entity is revoked
|
||||
@@ -551,15 +582,11 @@ func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader,
|
||||
// NOTE: The order of these checks is important, as the caller may choose to
|
||||
// ignore ErrSignatureExpired or ErrKeyExpired errors, but should never
|
||||
// ignore any other errors.
|
||||
//
|
||||
// TODO: Also return an error if:
|
||||
// - The primary key is expired according to a direct-key signature
|
||||
// - (For V5 keys only:) The direct-key signature (exists and) is expired
|
||||
func checkSignatureDetails(key *Key, signature *packet.Signature, config *packet.Config) error {
|
||||
func checkMessageSignatureDetails(key *Key, signature *packet.Signature, config *packet.Config) error {
|
||||
now := config.Now()
|
||||
primaryIdentity := key.Entity.PrimaryIdentity()
|
||||
primarySelfSignature, primaryIdentity := key.Entity.PrimarySelfSignature()
|
||||
signedBySubKey := key.PublicKey != key.Entity.PrimaryKey
|
||||
sigsToCheck := []*packet.Signature{signature, primaryIdentity.SelfSignature}
|
||||
sigsToCheck := []*packet.Signature{signature, primarySelfSignature}
|
||||
if signedBySubKey {
|
||||
sigsToCheck = append(sigsToCheck, key.SelfSignature, key.SelfSignature.EmbeddedSignature)
|
||||
}
|
||||
@@ -572,10 +599,10 @@ func checkSignatureDetails(key *Key, signature *packet.Signature, config *packet
|
||||
}
|
||||
if key.Entity.Revoked(now) || // primary key is revoked
|
||||
(signedBySubKey && key.Revoked(now)) || // subkey is revoked
|
||||
primaryIdentity.Revoked(now) { // primary identity is revoked
|
||||
(primaryIdentity != nil && primaryIdentity.Revoked(now)) { // primary identity is revoked for v4
|
||||
return errors.ErrKeyRevoked
|
||||
}
|
||||
if key.Entity.PrimaryKey.KeyExpired(primaryIdentity.SelfSignature, now) { // primary key is expired
|
||||
if key.Entity.PrimaryKey.KeyExpired(primarySelfSignature, now) { // primary key is expired
|
||||
return errors.ErrKeyExpired
|
||||
}
|
||||
if signedBySubKey {
|
||||
|
||||
201
vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go
generated
vendored
201
vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go
generated
vendored
@@ -26,6 +26,8 @@ const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a43129
|
||||
|
||||
const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000"
|
||||
|
||||
const ed25519wX25519Key = "c54b0663877fe31b00000020f94da7bb48d60a61e567706a6587d0331999bb9d891a08242ead84543df895a3001972817b12be707e8d5f586ce61361201d344eb266a2c82fde6835762b65b0b7c2b1061f1b0a00000042058263877fe3030b090705150a0e080c021600029b03021e09222106cb186c4f0609a697e4d52dfa6c722b0c1f1e27c18a56708f6525ec27bad9acc905270902070200000000ad2820103e2d7d227ec0e6d7ce4471db36bfc97083253690271498a7ef0576c07faae14585b3b903b0127ec4fda2f023045a2ec76bcb4f9571a9651e14aee1137a1d668442c88f951e33c4ffd33fb9a17d511eed758fc6d9cc50cb5fd793b2039d5804c74b0663877fe319000000208693248367f9e5015db922f8f48095dda784987f2d5985b12fbad16caf5e4435004d600a4f794d44775c57a26e0feefed558e9afffd6ad0d582d57fb2ba2dcedb8c29b06181b0a0000002c050263877fe322a106cb186c4f0609a697e4d52dfa6c722b0c1f1e27c18a56708f6525ec27bad9acc9021b0c00000000defa20a6e9186d9d5935fc8fe56314cdb527486a5a5120f9b762a235a729f039010a56b89c658568341fbef3b894e9834ad9bc72afae2f4c9c47a43855e65f1cb0a3f77bbc5f61085c1f8249fe4e7ca59af5f0bcee9398e0fa8d76e522e1d8ab42bb0d"
|
||||
|
||||
const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300"
|
||||
|
||||
const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200"
|
||||
@@ -160,18 +162,78 @@ TcIYl5/Uyoi+FOvPLcNw4hOv2nwUzSSVAw==
|
||||
=IiS2
|
||||
-----END PGP PRIVATE KEY BLOCK-----`
|
||||
|
||||
// Generated with the above private key
|
||||
const v5PrivKeyMsg = `-----BEGIN PGP MESSAGE-----
|
||||
Version: OpenPGP.js v4.10.7
|
||||
Comment: https://openpgpjs.org
|
||||
// See OpenPGP crypto refresh Section A.3.
|
||||
const v6PrivKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
xA0DAQoWGTR7yYckZAIByxF1B21zZy50eHRfbIGSdGVzdMJ3BQEWCgAGBQJf
|
||||
bIGSACMiIQUZNHvJhyRkAl+Z3z7C4AAO2YhIkuH3s+pMlACRWVabVDQvAP9G
|
||||
y29VPonFXqi2zKkpZrvyvZxg+n5e8Nt9wNbuxeCd3QD/TtO2s+JvjrE4Siwv
|
||||
UQdl5MlBka1QSNbMq2Bz7XwNPg4=
|
||||
=6lbM
|
||||
xUsGY4d/4xsAAAAg+U2nu0jWCmHlZ3BqZYfQMxmZu52JGggkLq2EVD34laMAGXKB
|
||||
exK+cH6NX1hs5hNhIB00TrJmosgv3mg1ditlsLfCsQYfGwoAAABCBYJjh3/jAwsJ
|
||||
BwUVCg4IDAIWAAKbAwIeCSIhBssYbE8GCaaX5NUt+mxyKwwfHifBilZwj2Ul7Ce6
|
||||
2azJBScJAgcCAAAAAK0oIBA+LX0ifsDm185Ecds2v8lwgyU2kCcUmKfvBXbAf6rh
|
||||
RYWzuQOwEn7E/aLwIwRaLsdry0+VcallHhSu4RN6HWaEQsiPlR4zxP/TP7mhfVEe
|
||||
7XWPxtnMUMtf15OyA51YBMdLBmOHf+MZAAAAIIaTJINn+eUBXbki+PSAld2nhJh/
|
||||
LVmFsS+60WyvXkQ1AE1gCk95TUR3XFeibg/u/tVY6a//1q0NWC1X+yui3O24wpsG
|
||||
GBsKAAAALAWCY4d/4wKbDCIhBssYbE8GCaaX5NUt+mxyKwwfHifBilZwj2Ul7Ce6
|
||||
2azJAAAAAAQBIKbpGG2dWTX8j+VjFM21J0hqWlEg+bdiojWnKfA5AQpWUWtnNwDE
|
||||
M0g12vYxoWM8Y81W+bHBw805I8kWVkXU6vFOi+HWvv/ira7ofJu16NnoUkhclkUr
|
||||
k0mXubZvyl4GBg==
|
||||
-----END PGP PRIVATE KEY BLOCK-----`
|
||||
|
||||
// See OpenPGP crypto refresh merge request:
|
||||
// https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/304
|
||||
const v6PrivKeyMsg = `-----BEGIN PGP MESSAGE-----
|
||||
|
||||
wV0GIQYSyD8ecG9jCP4VGkF3Q6HwM3kOk+mXhIjR2zeNqZMIhRmHzxjV8bU/gXzO
|
||||
WgBM85PMiVi93AZfJfhK9QmxfdNnZBjeo1VDeVZheQHgaVf7yopqR6W1FT6NOrfS
|
||||
aQIHAgZhZBZTW+CwcW1g4FKlbExAf56zaw76/prQoN+bAzxpohup69LA7JW/Vp0l
|
||||
yZnuSj3hcFj0DfqLTGgr4/u717J+sPWbtQBfgMfG9AOIwwrUBqsFE9zW+f1zdlYo
|
||||
bhF30A+IitsxxA==
|
||||
-----END PGP MESSAGE-----`
|
||||
|
||||
// See OpenPGP crypto refresh merge request:
|
||||
// https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/305
|
||||
const v6PrivKeyInlineSignMsg = `-----BEGIN PGP MESSAGE-----
|
||||
|
||||
wV0GIQYSyD8ecG9jCP4VGkF3Q6HwM3kOk+mXhIjR2zeNqZMIhRmHzxjV8bU/gXzO
|
||||
WgBM85PMiVi93AZfJfhK9QmxfdNnZBjeo1VDeVZheQHgaVf7yopqR6W1FT6NOrfS
|
||||
aQIHAgZhZBZTW+CwcW1g4FKlbExAf56zaw76/prQoN+bAzxpohup69LA7JW/Vp0l
|
||||
yZnuSj3hcFj0DfqLTGgr4/u717J+sPWbtQBfgMfG9AOIwwrUBqsFE9zW+f1zdlYo
|
||||
bhF30A+IitsxxA==
|
||||
-----END PGP MESSAGE-----`
|
||||
|
||||
// See https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/274
|
||||
// decryption password: "correct horse battery staple"
|
||||
const v6ArgonSealedPrivKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
xYIGY4d/4xsAAAAg+U2nu0jWCmHlZ3BqZYfQMxmZu52JGggkLq2EVD34laP9JgkC
|
||||
FARdb9ccngltHraRe25uHuyuAQQVtKipJ0+r5jL4dacGWSAheCWPpITYiyfyIOPS
|
||||
3gIDyg8f7strd1OB4+LZsUhcIjOMpVHgmiY/IutJkulneoBYwrEGHxsKAAAAQgWC
|
||||
Y4d/4wMLCQcFFQoOCAwCFgACmwMCHgkiIQbLGGxPBgmml+TVLfpscisMHx4nwYpW
|
||||
cI9lJewnutmsyQUnCQIHAgAAAACtKCAQPi19In7A5tfORHHbNr/JcIMlNpAnFJin
|
||||
7wV2wH+q4UWFs7kDsBJ+xP2i8CMEWi7Ha8tPlXGpZR4UruETeh1mhELIj5UeM8T/
|
||||
0z+5oX1RHu11j8bZzFDLX9eTsgOdWATHggZjh3/jGQAAACCGkySDZ/nlAV25Ivj0
|
||||
gJXdp4SYfy1ZhbEvutFsr15ENf0mCQIUBA5hhGgp2oaavg6mFUXcFMwBBBUuE8qf
|
||||
9Ock+xwusd+GAglBr5LVyr/lup3xxQvHXFSjjA2haXfoN6xUGRdDEHI6+uevKjVR
|
||||
v5oAxgu7eJpaXNjCmwYYGwoAAAAsBYJjh3/jApsMIiEGyxhsTwYJppfk1S36bHIr
|
||||
DB8eJ8GKVnCPZSXsJ7rZrMkAAAAABAEgpukYbZ1ZNfyP5WMUzbUnSGpaUSD5t2Ki
|
||||
Nacp8DkBClZRa2c3AMQzSDXa9jGhYzxjzVb5scHDzTkjyRZWRdTq8U6L4da+/+Kt
|
||||
ruh8m7Xo2ehSSFyWRSuTSZe5tm/KXgYG
|
||||
-----END PGP PRIVATE KEY BLOCK-----`
|
||||
|
||||
const v4Key25519 = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
xUkEZB3qzRto01j2k2pwN5ux9w70stPinAdXULLr20CRW7U7h2GSeACch0M+
|
||||
qzQg8yjFQ8VBvu3uwgKH9senoHmj72lLSCLTmhFKzQR0ZXN0wogEEBsIAD4F
|
||||
gmQd6s0ECwkHCAmQIf45+TuC+xMDFQgKBBYAAgECGQECmwMCHgEWIQSWEzMi
|
||||
jJUHvyIbVKIh/jn5O4L7EwAAUhaHNlgudvxARdPPETUzVgjuWi+YIz8w1xIb
|
||||
lHQMvIrbe2sGCQIethpWofd0x7DHuv/ciHg+EoxJ/Td6h4pWtIoKx0kEZB3q
|
||||
zRm4CyA7quliq7yx08AoOqHTuuCgvpkSdEhpp3pEyejQOgBo0p6ywIiLPllY
|
||||
0t+jpNspHpAGfXID6oqjpYuJw3AfVRBlwnQEGBsIACoFgmQd6s0JkCH+Ofk7
|
||||
gvsTApsMFiEElhMzIoyVB78iG1SiIf45+TuC+xMAAGgQuN9G73446ykvJ/mL
|
||||
sCZ7zGFId2gBd1EnG0FTC4npfOKpck0X8dngByrCxU8LDSfvjsEp/xDAiKsQ
|
||||
aU71tdtNBQ==
|
||||
=e7jT
|
||||
-----END PGP PRIVATE KEY BLOCK-----`
|
||||
|
||||
const keyWithExpiredCrossSig = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
xsDNBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv
|
||||
@@ -272,3 +334,124 @@ AtNTq6ihLMD5v1d82ZC7tNatdlDMGWnIdvEMCv2GZcuIqDQ9rXWs49e7tq1NncLY
|
||||
hz3tYjKhoFTKEIq3y3Pp
|
||||
=h/aX
|
||||
-----END PGP PUBLIC KEY BLOCK-----`
|
||||
|
||||
const keyv5Test = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
Comment: Bob's OpenPGP Transferable Secret Key
|
||||
|
||||
lQVYBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv
|
||||
/seOXpgecTdOcVttfzC8ycIKrt3aQTiwOG/ctaR4Bk/t6ayNFfdUNxHWk4WCKzdz
|
||||
/56fW2O0F23qIRd8UUJp5IIlN4RDdRCtdhVQIAuzvp2oVy/LaS2kxQoKvph/5pQ/
|
||||
5whqsyroEWDJoSV0yOb25B/iwk/pLUFoyhDG9bj0kIzDxrEqW+7Ba8nocQlecMF3
|
||||
X5KMN5kp2zraLv9dlBBpWW43XktjcCZgMy20SouraVma8Je/ECwUWYUiAZxLIlMv
|
||||
9CurEOtxUw6N3RdOtLmYZS9uEnn5y1UkF88o8Nku890uk6BrewFzJyLAx5wRZ4F0
|
||||
qV/yq36UWQ0JB/AUGhHVPdFf6pl6eaxBwT5GXvbBUibtf8YI2og5RsgTWtXfU7eb
|
||||
SGXrl5ZMpbA6mbfhd0R8aPxWfmDWiIOhBufhMCvUHh1sApMKVZnvIff9/0Dca3wb
|
||||
vLIwa3T4CyshfT0AEQEAAQAL/RZqbJW2IqQDCnJi4Ozm++gPqBPiX1RhTWSjwxfM
|
||||
cJKUZfzLj414rMKm6Jh1cwwGY9jekROhB9WmwaaKT8HtcIgrZNAlYzANGRCM4TLK
|
||||
3VskxfSwKKna8l+s+mZglqbAjUg3wmFuf9Tj2xcUZYmyRm1DEmcN2ZzpvRtHgX7z
|
||||
Wn1mAKUlSDJZSQks0zjuMNbupcpyJokdlkUg2+wBznBOTKzgMxVNC9b2g5/tMPUs
|
||||
hGGWmF1UH+7AHMTaS6dlmr2ZBIyogdnfUqdNg5sZwsxSNrbglKP4sqe7X61uEAIQ
|
||||
bD7rT3LonLbhkrj3I8wilUD8usIwt5IecoHhd9HziqZjRCc1BUBkboUEoyedbDV4
|
||||
i4qfsFZ6CEWoLuD5pW7dEp0M+WeuHXO164Rc+LnH6i1VQrpb1Okl4qO6ejIpIjBI
|
||||
1t3GshtUu/mwGBBxs60KBX5g77mFQ9lLCRj8lSYqOsHRKBhUp4qM869VA+fD0BRP
|
||||
fqPT0I9IH4Oa/A3jYJcg622GwQYA1LhnP208Waf6PkQSJ6kyr8ymY1yVh9VBE/g6
|
||||
fRDYA+pkqKnw9wfH2Qho3ysAA+OmVOX8Hldg+Pc0Zs0e5pCavb0En8iFLvTA0Q2E
|
||||
LR5rLue9uD7aFuKFU/VdcddY9Ww/vo4k5p/tVGp7F8RYCFn9rSjIWbfvvZi1q5Tx
|
||||
+akoZbga+4qQ4WYzB/obdX6SCmi6BndcQ1QdjCCQU6gpYx0MddVERbIp9+2SXDyL
|
||||
hpxjSyz+RGsZi/9UAshT4txP4+MZBgDfK3ZqtW+h2/eMRxkANqOJpxSjMyLO/FXN
|
||||
WxzTDYeWtHNYiAlOwlQZEPOydZFty9IVzzNFQCIUCGjQ/nNyhw7adSgUk3+BXEx/
|
||||
MyJPYY0BYuhLxLYcrfQ9nrhaVKxRJj25SVHj2ASsiwGJRZW4CC3uw40OYxfKEvNC
|
||||
mer/VxM3kg8qqGf9KUzJ1dVdAvjyx2Hz6jY2qWCyRQ6IMjWHyd43C4r3jxooYKUC
|
||||
YnstRQyb/gCSKahveSEjo07CiXMr88UGALwzEr3npFAsPW3osGaFLj49y1oRe11E
|
||||
he9gCHFm+fuzbXrWmdPjYU5/ZdqdojzDqfu4ThfnipknpVUM1o6MQqkjM896FHm8
|
||||
zbKVFSMhEP6DPHSCexMFrrSgN03PdwHTO6iBaIBBFqmGY01tmJ03SxvSpiBPON9P
|
||||
NVvy/6UZFedTq8A07OUAxO62YUSNtT5pmK2vzs3SAZJmbFbMh+NN204TRI72GlqT
|
||||
t5hcfkuv8hrmwPS/ZR6q312mKQ6w/1pqO9qitCFCb2IgQmFiYmFnZSA8Ym9iQG9w
|
||||
ZW5wZ3AuZXhhbXBsZT6JAc4EEwEKADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgEC
|
||||
F4AWIQTRpm4aI7GCyZgPeIz7/MgqAV5zMAUCXaWe+gAKCRD7/MgqAV5zMG9sC/9U
|
||||
2T3RrqEbw533FPNfEflhEVRIZ8gDXKM8hU6cqqEzCmzZT6xYTe6sv4y+PJBGXJFX
|
||||
yhj0g6FDkSyboM5litOcTupURObVqMgA/Y4UKERznm4fzzH9qek85c4ljtLyNufe
|
||||
doL2pp3vkGtn7eD0QFRaLLmnxPKQ/TlZKdLE1G3u8Uot8QHicaR6GnAdc5UXQJE3
|
||||
BiV7jZuDyWmZ1cUNwJkKL6oRtp+ZNDOQCrLNLecKHcgCqrpjSQG5oouba1I1Q6Vl
|
||||
sP44dhA1nkmLHtxlTOzpeHj4jnk1FaXmyasurrrI5CgU/L2Oi39DGKTH/A/cywDN
|
||||
4ZplIQ9zR8enkbXquUZvFDe+Xz+6xRXtb5MwQyWODB3nHw85HocLwRoIN9WdQEI+
|
||||
L8a/56AuOwhs8llkSuiITjR7r9SgKJC2WlAHl7E8lhJ3VDW3ELC56KH308d6mwOG
|
||||
ZRAqIAKzM1T5FGjMBhq7ZV0eqdEntBh3EcOIfj2M8rg1MzJv+0mHZOIjByawikad
|
||||
BVgEXaWc8gEMANYwv1xsYyunXYK0X1vY/rP1NNPvhLyLIE7NpK90YNBj+xS1ldGD
|
||||
bUdZqZeef2xJe8gMQg05DoD1DF3GipZ0Ies65beh+d5hegb7N4pzh0LzrBrVNHar
|
||||
29b5ExdI7i4iYD5TO6Vr/qTUOiAN/byqELEzAb+L+b2DVz/RoCm4PIp1DU9ewcc2
|
||||
WB38Ofqut3nLYA5tqJ9XvAiEQme+qAVcM3ZFcaMt4I4dXhDZZNg+D9LiTWcxdUPB
|
||||
leu8iwDRjAgyAhPzpFp+nWoqWA81uIiULWD1Fj+IVoY3ZvgivoYOiEFBJ9lbb4te
|
||||
g9m5UT/AaVDTWuHzbspVlbiVe+qyB77C2daWzNyx6UYBPLOo4r0t0c91kbNE5lgj
|
||||
Z7xz6los0N1U8vq91EFSeQJoSQ62XWavYmlCLmdNT6BNfgh4icLsT7Vr1QMX9jzn
|
||||
JtTPxdXytSdHvpSpULsqJ016l0dtmONcK3z9mj5N5z0k1tg1AH970TGYOe2aUcSx
|
||||
IRDMXDOPyzEfjwARAQABAAv9F2CwsjS+Sjh1M1vegJbZjei4gF1HHpEM0K0PSXsp
|
||||
SfVvpR4AoSJ4He6CXSMWg0ot8XKtDuZoV9jnJaES5UL9pMAD7JwIOqZm/DYVJM5h
|
||||
OASCh1c356/wSbFbzRHPtUdZO9Q30WFNJM5pHbCJPjtNoRmRGkf71RxtvHBzy7np
|
||||
Ga+W6U/NVKHw0i0CYwMI0YlKDakYW3Pm+QL+gHZFvngGweTod0f9l2VLLAmeQR/c
|
||||
+EZs7lNumhuZ8mXcwhUc9JQIhOkpO+wreDysEFkAcsKbkQP3UDUsA1gFx9pbMzT0
|
||||
tr1oZq2a4QBtxShHzP/ph7KLpN+6qtjks3xB/yjTgaGmtrwM8tSe0wD1RwXS+/1o
|
||||
BHpXTnQ7TfeOGUAu4KCoOQLv6ELpKWbRBLWuiPwMdbGpvVFALO8+kvKAg9/r+/ny
|
||||
zM2GQHY+J3Jh5JxPiJnHfXNZjIKLbFbIPdSKNyJBuazXW8xIa//mEHMI5OcvsZBK
|
||||
clAIp7LXzjEjKXIwHwDcTn9pBgDpdOKTHOtJ3JUKx0rWVsDH6wq6iKV/FTVSY5jl
|
||||
zN+puOEsskF1Lfxn9JsJihAVO3yNsp6RvkKtyNlFazaCVKtDAmkjoh60XNxcNRqr
|
||||
gCnwdpbgdHP6v/hvZY54ZaJjz6L2e8unNEkYLxDt8cmAyGPgH2XgL7giHIp9jrsQ
|
||||
aS381gnYwNX6wE1aEikgtY91nqJjwPlibF9avSyYQoMtEqM/1UjTjB2KdD/MitK5
|
||||
fP0VpvuXpNYZedmyq4UOMwdkiNMGAOrfmOeT0olgLrTMT5H97Cn3Yxbk13uXHNu/
|
||||
ZUZZNe8s+QtuLfUlKAJtLEUutN33TlWQY522FV0m17S+b80xJib3yZVJteVurrh5
|
||||
HSWHAM+zghQAvCesg5CLXa2dNMkTCmZKgCBvfDLZuZbjFwnwCI6u/NhOY9egKuUf
|
||||
SA/je/RXaT8m5VxLYMxwqQXKApzD87fv0tLPlVIEvjEsaf992tFEFSNPcG1l/jpd
|
||||
5AVXw6kKuf85UkJtYR1x2MkQDrqY1QX/XMw00kt8y9kMZUre19aCArcmor+hDhRJ
|
||||
E3Gt4QJrD9z/bICESw4b4z2DbgD/Xz9IXsA/r9cKiM1h5QMtXvuhyfVeM01enhxM
|
||||
GbOH3gjqqGNKysx0UODGEwr6AV9hAd8RWXMchJLaExK9J5SRawSg671ObAU24SdY
|
||||
vMQ9Z4kAQ2+1ReUZzf3ogSMRZtMT+d18gT6L90/y+APZIaoArLPhebIAGq39HLmJ
|
||||
26x3z0WAgrpA1kNsjXEXkoiZGPLKIGoe3hqJAbYEGAEKACAWIQTRpm4aI7GCyZgP
|
||||
eIz7/MgqAV5zMAUCXaWc8gIbDAAKCRD7/MgqAV5zMOn/C/9ugt+HZIwX308zI+QX
|
||||
c5vDLReuzmJ3ieE0DMO/uNSC+K1XEioSIZP91HeZJ2kbT9nn9fuReuoff0T0Dief
|
||||
rbwcIQQHFFkrqSp1K3VWmUGp2JrUsXFVdjy/fkBIjTd7c5boWljv/6wAsSfiv2V0
|
||||
JSM8EFU6TYXxswGjFVfc6X97tJNeIrXL+mpSmPPqy2bztcCCHkWS5lNLWQw+R7Vg
|
||||
71Fe6yBSNVrqC2/imYG2J9zlowjx1XU63Wdgqp2Wxt0l8OmsB/W80S1fRF5G4SDH
|
||||
s9HXglXXqPsBRZJYfP+VStm9L5P/sKjCcX6WtZR7yS6G8zj/X767MLK/djANvpPd
|
||||
NVniEke6hM3CNBXYPAMhQBMWhCulcoz+0lxi8L34rMN+Dsbma96psdUrn7uLaB91
|
||||
6we0CTfF8qqm7BsVAgalon/UUiuMY80U3ueoj3okiSTiHIjD/YtpXSPioC8nMng7
|
||||
xqAY9Bwizt4FWgXuLm1a4+So4V9j1TRCXd12Uc2l2RNmgDE=
|
||||
=miES
|
||||
-----END PGP PRIVATE KEY BLOCK-----
|
||||
`
|
||||
|
||||
const certv5Test = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
lGEFXJH05BYAAAAtCSsGAQQB2kcPAQEHQFhZlVcVVtwf+21xNQPX+ecMJJBL0MPd
|
||||
fj75iux+my8QAAAAAAAiAQCHZ1SnSUmWqxEsoI6facIVZQu6mph3cBFzzTvcm5lA
|
||||
Ng5ctBhlbW1hLmdvbGRtYW5AZXhhbXBsZS5uZXSIlgUTFggASCIhBRk0e8mHJGQC
|
||||
X5nfPsLgAA7ZiEiS4fez6kyUAJFZVptUBQJckfTkAhsDBQsJCAcCAyICAQYVCgkI
|
||||
CwIEFgIDAQIeBwIXgAAA9cAA/jiR3yMsZMeEQ40u6uzEoXa6UXeV/S3wwJAXRJy9
|
||||
M8s0AP9vuL/7AyTfFXwwzSjDnYmzS0qAhbLDQ643N+MXGBJ2BZxmBVyR9OQSAAAA
|
||||
MgorBgEEAZdVAQUBAQdA+nysrzml2UCweAqtpDuncSPlvrcBWKU0yfU0YvYWWAoD
|
||||
AQgHAAAAAAAiAP9OdAPppjU1WwpqjIItkxr+VPQRT8Zm/Riw7U3F6v3OiBFHiHoF
|
||||
GBYIACwiIQUZNHvJhyRkAl+Z3z7C4AAO2YhIkuH3s+pMlACRWVabVAUCXJH05AIb
|
||||
DAAAOSQBAP4BOOIR/sGLNMOfeb5fPs/02QMieoiSjIBnijhob2U5AQC+RtOHCHx7
|
||||
TcIYl5/Uyoi+FOvPLcNw4hOv2nwUzSSVAw==
|
||||
=IiS2
|
||||
-----END PGP PRIVATE KEY BLOCK-----
|
||||
`
|
||||
|
||||
const msgv5Test = `-----BEGIN PGP MESSAGE-----
|
||||
|
||||
wcDMA3wvqk35PDeyAQv+PcQiLsoYTH30nJYQh3j3cJaO2+jErtVCrIQRIU0+
|
||||
rmgMddERYST4A9mA0DQIiTI4FQ0Lp440D3BWCgpq3LlNWewGzduaWwym5rN6
|
||||
cwHz5ccDqOcqbd9X0GXXGy/ZH/ljSgzuVMIytMAXKdF/vrRrVgH/+I7cxvm9
|
||||
HwnhjMN5dF0j4aEt996H2T7cbtzSr2GN9SWGW8Gyu7I8Zx73hgrGUI7gDiJB
|
||||
Afaff+P6hfkkHSGOItr94dde8J/7AUF4VEwwxdVVPvsNEFyvv6gRIbYtOCa2
|
||||
6RE6h1V/QTxW2O7zZgzWALrE2ui0oaYr9QuqQSssd9CdgExLfdPbI+3/ZAnE
|
||||
v31Idzpk3/6ILiakYHtXkElPXvf46mCNpobty8ysT34irF+fy3C1p3oGwAsx
|
||||
5VDV9OSFU6z5U+UPbSPYAy9rkc5ZssuIKxCER2oTvZ2L8Q5cfUvEUiJtRGGn
|
||||
CJlHrVDdp3FssKv2tlKgLkvxJLyoOjuEkj44H1qRk+D02FzmmUT/0sAHAYYx
|
||||
lTir6mjHeLpcGjn4waUuWIAJyph8SxUexP60bic0L0NBa6Qp5SxxijKsPIDb
|
||||
FPHxWwfJSDZRrgUyYT7089YFB/ZM4FHyH9TZcnxn0f0xIB7NS6YNDsxzN2zT
|
||||
EVEYf+De4qT/dQTsdww78Chtcv9JY9r2kDm77dk2MUGHL2j7n8jasbLtgA7h
|
||||
pn2DMIWLrGamMLWRmlwslolKr1sMV5x8w+5Ias6C33iBMl9phkg42an0gYmc
|
||||
byVJHvLO/XErtC+GNIJeMg==
|
||||
=liRq
|
||||
-----END PGP MESSAGE-----
|
||||
`
|
||||
|
||||
35
vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go
generated
vendored
35
vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go
generated
vendored
@@ -283,6 +283,9 @@ func ParseIntoParams(r io.Reader) (params *Params, err error) {
|
||||
params.passes = buf[Argon2SaltSize]
|
||||
params.parallelism = buf[Argon2SaltSize+1]
|
||||
params.memoryExp = buf[Argon2SaltSize+2]
|
||||
if err := validateArgon2Params(params); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return params, nil
|
||||
case GnuS2K:
|
||||
// This is a GNU extension. See
|
||||
@@ -300,15 +303,22 @@ func ParseIntoParams(r io.Reader) (params *Params, err error) {
|
||||
return nil, errors.UnsupportedError("S2K function")
|
||||
}
|
||||
|
||||
func (params *Params) Mode() Mode {
|
||||
return params.mode
|
||||
}
|
||||
|
||||
func (params *Params) Dummy() bool {
|
||||
return params != nil && params.mode == GnuS2K
|
||||
}
|
||||
|
||||
func (params *Params) salt() []byte {
|
||||
switch params.mode {
|
||||
case SaltedS2K, IteratedSaltedS2K: return params.saltBytes[:8]
|
||||
case Argon2S2K: return params.saltBytes[:Argon2SaltSize]
|
||||
default: return nil
|
||||
case SaltedS2K, IteratedSaltedS2K:
|
||||
return params.saltBytes[:8]
|
||||
case Argon2S2K:
|
||||
return params.saltBytes[:Argon2SaltSize]
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,3 +415,22 @@ func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Co
|
||||
f(key, passphrase)
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateArgon2Params checks that the argon2 parameters are valid according to RFC9580.
|
||||
func validateArgon2Params(params *Params) error {
|
||||
// The number of passes t and the degree of parallelism p MUST be non-zero.
|
||||
if params.parallelism == 0 {
|
||||
return errors.StructuralError("invalid argon2 params: parallelism is 0")
|
||||
}
|
||||
if params.passes == 0 {
|
||||
return errors.StructuralError("invalid argon2 params: iterations is 0")
|
||||
}
|
||||
|
||||
// The encoded memory size MUST be a value from 3+ceil(log2(p)) to 31,
|
||||
// such that the decoded memory size m is a value from 8*p to 2^31.
|
||||
if params.memoryExp > 31 || decodeMemory(params.memoryExp) < 8*uint32(params.parallelism) {
|
||||
return errors.StructuralError("invalid argon2 params: memory is out of bounds")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
2
vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_config.go
generated
vendored
2
vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_config.go
generated
vendored
@@ -50,7 +50,7 @@ type Config struct {
|
||||
type Argon2Config struct {
|
||||
NumberOfPasses uint8
|
||||
DegreeOfParallelism uint8
|
||||
// The memory parameter for Argon2 specifies desired memory usage in kibibytes.
|
||||
// Memory specifies the desired Argon2 memory usage in kibibytes.
|
||||
// For example memory=64*1024 sets the memory cost to ~64 MB.
|
||||
Memory uint32
|
||||
}
|
||||
|
||||
189
vendor/github.com/ProtonMail/go-crypto/openpgp/write.go
generated
vendored
189
vendor/github.com/ProtonMail/go-crypto/openpgp/write.go
generated
vendored
@@ -76,7 +76,11 @@ func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.S
|
||||
|
||||
sig := createSignaturePacket(signingKey.PublicKey, sigType, config)
|
||||
|
||||
h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
|
||||
h, err := sig.PrepareSign(config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
wrappedHash, err := wrapHashForSignature(h, sig.SigType)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -249,40 +253,32 @@ func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entit
|
||||
}
|
||||
|
||||
var hash crypto.Hash
|
||||
for _, hashId := range candidateHashes {
|
||||
if h, ok := algorithm.HashIdToHash(hashId); ok && h.Available() {
|
||||
hash = h
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If the hash specified by config is a candidate, we'll use that.
|
||||
if configuredHash := config.Hash(); configuredHash.Available() {
|
||||
for _, hashId := range candidateHashes {
|
||||
if h, ok := algorithm.HashIdToHash(hashId); ok && h == configuredHash {
|
||||
hash = h
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if hash == 0 {
|
||||
hashId := candidateHashes[0]
|
||||
name, ok := algorithm.HashIdToString(hashId)
|
||||
if !ok {
|
||||
name = "#" + strconv.Itoa(int(hashId))
|
||||
}
|
||||
return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)")
|
||||
}
|
||||
|
||||
var salt []byte
|
||||
if signer != nil {
|
||||
if hash, err = selectHash(candidateHashes, config.Hash(), signer); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var opsVersion = 3
|
||||
if signer.Version == 6 {
|
||||
opsVersion = signer.Version
|
||||
}
|
||||
ops := &packet.OnePassSignature{
|
||||
Version: opsVersion,
|
||||
SigType: sigType,
|
||||
Hash: hash,
|
||||
PubKeyAlgo: signer.PubKeyAlgo,
|
||||
KeyId: signer.KeyId,
|
||||
IsLast: true,
|
||||
}
|
||||
if opsVersion == 6 {
|
||||
ops.KeyFingerprint = signer.Fingerprint
|
||||
salt, err = packet.SignatureSaltForHash(hash, config.Random())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ops.Salt = salt
|
||||
}
|
||||
if err := ops.Serialize(payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -310,19 +306,19 @@ func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entit
|
||||
}
|
||||
|
||||
if signer != nil {
|
||||
h, wrappedHash, err := hashForSignature(hash, sigType)
|
||||
h, wrappedHash, err := hashForSignature(hash, sigType, salt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
metadata := &packet.LiteralData{
|
||||
Format: 't',
|
||||
Format: 'u',
|
||||
FileName: hints.FileName,
|
||||
Time: epochSeconds,
|
||||
}
|
||||
if hints.IsBinary {
|
||||
metadata.Format = 'b'
|
||||
}
|
||||
return signatureWriter{payload, literalData, hash, wrappedHash, h, signer, sigType, config, metadata}, nil
|
||||
return signatureWriter{payload, literalData, hash, wrappedHash, h, salt, signer, sigType, config, metadata}, nil
|
||||
}
|
||||
return literalData, nil
|
||||
}
|
||||
@@ -380,15 +376,19 @@ func encrypt(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *En
|
||||
return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no valid encryption keys")
|
||||
}
|
||||
|
||||
sig := to[i].PrimaryIdentity().SelfSignature
|
||||
if !sig.SEIPDv2 {
|
||||
primarySelfSignature, _ := to[i].PrimarySelfSignature()
|
||||
if primarySelfSignature == nil {
|
||||
return nil, errors.InvalidArgumentError("entity without a self-signature")
|
||||
}
|
||||
|
||||
if !primarySelfSignature.SEIPDv2 {
|
||||
aeadSupported = false
|
||||
}
|
||||
|
||||
candidateCiphers = intersectPreferences(candidateCiphers, sig.PreferredSymmetric)
|
||||
candidateHashes = intersectPreferences(candidateHashes, sig.PreferredHash)
|
||||
candidateCipherSuites = intersectCipherSuites(candidateCipherSuites, sig.PreferredCipherSuites)
|
||||
candidateCompression = intersectPreferences(candidateCompression, sig.PreferredCompression)
|
||||
candidateCiphers = intersectPreferences(candidateCiphers, primarySelfSignature.PreferredSymmetric)
|
||||
candidateHashes = intersectPreferences(candidateHashes, primarySelfSignature.PreferredHash)
|
||||
candidateCipherSuites = intersectCipherSuites(candidateCipherSuites, primarySelfSignature.PreferredCipherSuites)
|
||||
candidateCompression = intersectPreferences(candidateCompression, primarySelfSignature.PreferredCompression)
|
||||
}
|
||||
|
||||
// In the event that the intersection of supported algorithms is empty we use the ones
|
||||
@@ -422,13 +422,19 @@ func encrypt(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *En
|
||||
}
|
||||
}
|
||||
|
||||
symKey := make([]byte, cipher.KeySize())
|
||||
var symKey []byte
|
||||
if aeadSupported {
|
||||
symKey = make([]byte, aeadCipherSuite.Cipher.KeySize())
|
||||
} else {
|
||||
symKey = make([]byte, cipher.KeySize())
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(config.Random(), symKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, key := range encryptKeys {
|
||||
if err := packet.SerializeEncryptedKey(keyWriter, key.PublicKey, cipher, symKey, config); err != nil {
|
||||
if err := packet.SerializeEncryptedKeyAEAD(keyWriter, key.PublicKey, cipher, aeadSupported, symKey, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -465,13 +471,17 @@ func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Con
|
||||
hashToHashId(crypto.SHA3_512),
|
||||
}
|
||||
defaultHashes := candidateHashes[0:1]
|
||||
preferredHashes := signed.PrimaryIdentity().SelfSignature.PreferredHash
|
||||
primarySelfSignature, _ := signed.PrimarySelfSignature()
|
||||
if primarySelfSignature == nil {
|
||||
return nil, errors.StructuralError("signed entity has no self-signature")
|
||||
}
|
||||
preferredHashes := primarySelfSignature.PreferredHash
|
||||
if len(preferredHashes) == 0 {
|
||||
preferredHashes = defaultHashes
|
||||
}
|
||||
candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
|
||||
if len(candidateHashes) == 0 {
|
||||
return nil, errors.InvalidArgumentError("cannot sign because signing key shares no common algorithms with candidate hashes")
|
||||
return nil, errors.StructuralError("cannot sign because signing key shares no common algorithms with candidate hashes")
|
||||
}
|
||||
|
||||
return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, packet.SigTypeBinary, config)
|
||||
@@ -486,6 +496,7 @@ type signatureWriter struct {
|
||||
hashType crypto.Hash
|
||||
wrappedHash hash.Hash
|
||||
h hash.Hash
|
||||
salt []byte // v6 only
|
||||
signer *packet.PrivateKey
|
||||
sigType packet.SignatureType
|
||||
config *packet.Config
|
||||
@@ -509,6 +520,10 @@ func (s signatureWriter) Close() error {
|
||||
sig.Hash = s.hashType
|
||||
sig.Metadata = s.metadata
|
||||
|
||||
if err := sig.SetSalt(s.salt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := sig.Sign(s.h, s.signer, s.config); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -521,13 +536,34 @@ func (s signatureWriter) Close() error {
|
||||
return s.encryptedData.Close()
|
||||
}
|
||||
|
||||
func selectHashForSigningKey(config *packet.Config, signer *packet.PublicKey) crypto.Hash {
|
||||
acceptableHashes := acceptableHashesToWrite(signer)
|
||||
hash, ok := algorithm.HashToHashId(config.Hash())
|
||||
if !ok {
|
||||
return config.Hash()
|
||||
}
|
||||
for _, acceptableHashes := range acceptableHashes {
|
||||
if acceptableHashes == hash {
|
||||
return config.Hash()
|
||||
}
|
||||
}
|
||||
if len(acceptableHashes) > 0 {
|
||||
defaultAcceptedHash, ok := algorithm.HashIdToHash(acceptableHashes[0])
|
||||
if ok {
|
||||
return defaultAcceptedHash
|
||||
}
|
||||
}
|
||||
return config.Hash()
|
||||
}
|
||||
|
||||
func createSignaturePacket(signer *packet.PublicKey, sigType packet.SignatureType, config *packet.Config) *packet.Signature {
|
||||
sigLifetimeSecs := config.SigLifetime()
|
||||
hash := selectHashForSigningKey(config, signer)
|
||||
return &packet.Signature{
|
||||
Version: signer.Version,
|
||||
SigType: sigType,
|
||||
PubKeyAlgo: signer.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
Hash: hash,
|
||||
CreationTime: config.Now(),
|
||||
IssuerKeyId: &signer.KeyId,
|
||||
IssuerFingerprint: signer.Fingerprint,
|
||||
@@ -581,3 +617,74 @@ func handleCompression(compressed io.WriteCloser, candidateCompression []uint8,
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// selectHash selects the preferred hash given the candidateHashes and the configuredHash
|
||||
func selectHash(candidateHashes []byte, configuredHash crypto.Hash, signer *packet.PrivateKey) (hash crypto.Hash, err error) {
|
||||
acceptableHashes := acceptableHashesToWrite(&signer.PublicKey)
|
||||
candidateHashes = intersectPreferences(acceptableHashes, candidateHashes)
|
||||
|
||||
for _, hashId := range candidateHashes {
|
||||
if h, ok := algorithm.HashIdToHash(hashId); ok && h.Available() {
|
||||
hash = h
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If the hash specified by config is a candidate, we'll use that.
|
||||
if configuredHash.Available() {
|
||||
for _, hashId := range candidateHashes {
|
||||
if h, ok := algorithm.HashIdToHash(hashId); ok && h == configuredHash {
|
||||
hash = h
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if hash == 0 {
|
||||
if len(acceptableHashes) > 0 {
|
||||
if h, ok := algorithm.HashIdToHash(acceptableHashes[0]); ok {
|
||||
hash = h
|
||||
} else {
|
||||
return 0, errors.UnsupportedError("no candidate hash functions are compiled in.")
|
||||
}
|
||||
} else {
|
||||
return 0, errors.UnsupportedError("no candidate hash functions are compiled in.")
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func acceptableHashesToWrite(singingKey *packet.PublicKey) []uint8 {
|
||||
switch singingKey.PubKeyAlgo {
|
||||
case packet.PubKeyAlgoEd448:
|
||||
return []uint8{
|
||||
hashToHashId(crypto.SHA512),
|
||||
hashToHashId(crypto.SHA3_512),
|
||||
}
|
||||
case packet.PubKeyAlgoECDSA, packet.PubKeyAlgoEdDSA:
|
||||
if curve, err := singingKey.Curve(); err == nil {
|
||||
if curve == packet.Curve448 ||
|
||||
curve == packet.CurveNistP521 ||
|
||||
curve == packet.CurveBrainpoolP512 {
|
||||
return []uint8{
|
||||
hashToHashId(crypto.SHA512),
|
||||
hashToHashId(crypto.SHA3_512),
|
||||
}
|
||||
} else if curve == packet.CurveBrainpoolP384 ||
|
||||
curve == packet.CurveNistP384 {
|
||||
return []uint8{
|
||||
hashToHashId(crypto.SHA384),
|
||||
hashToHashId(crypto.SHA512),
|
||||
hashToHashId(crypto.SHA3_512),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return []uint8{
|
||||
hashToHashId(crypto.SHA256),
|
||||
hashToHashId(crypto.SHA384),
|
||||
hashToHashId(crypto.SHA512),
|
||||
hashToHashId(crypto.SHA3_256),
|
||||
hashToHashId(crypto.SHA3_512),
|
||||
}
|
||||
}
|
||||
|
||||
221
vendor/github.com/ProtonMail/go-crypto/openpgp/x25519/x25519.go
generated
vendored
Normal file
221
vendor/github.com/ProtonMail/go-crypto/openpgp/x25519/x25519.go
generated
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
package x25519
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/aes/keywrap"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
x25519lib "github.com/cloudflare/circl/dh/x25519"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
)
|
||||
|
||||
const (
|
||||
hkdfInfo = "OpenPGP X25519"
|
||||
aes128KeySize = 16
|
||||
// The size of a public or private key in bytes.
|
||||
KeySize = x25519lib.Size
|
||||
)
|
||||
|
||||
type PublicKey struct {
|
||||
// Point represents the encoded elliptic curve point of the public key.
|
||||
Point []byte
|
||||
}
|
||||
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
// Secret represents the secret of the private key.
|
||||
Secret []byte
|
||||
}
|
||||
|
||||
// NewPrivateKey creates a new empty private key including the public key.
|
||||
func NewPrivateKey(key PublicKey) *PrivateKey {
|
||||
return &PrivateKey{
|
||||
PublicKey: key,
|
||||
}
|
||||
}
|
||||
|
||||
// Validate validates that the provided public key matches the private key.
|
||||
func Validate(pk *PrivateKey) (err error) {
|
||||
var expectedPublicKey, privateKey x25519lib.Key
|
||||
subtle.ConstantTimeCopy(1, privateKey[:], pk.Secret)
|
||||
x25519lib.KeyGen(&expectedPublicKey, &privateKey)
|
||||
if subtle.ConstantTimeCompare(expectedPublicKey[:], pk.PublicKey.Point) == 0 {
|
||||
return errors.KeyInvalidError("x25519: invalid key")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateKey generates a new x25519 key pair.
|
||||
func GenerateKey(rand io.Reader) (*PrivateKey, error) {
|
||||
var privateKey, publicKey x25519lib.Key
|
||||
privateKeyOut := new(PrivateKey)
|
||||
err := generateKey(rand, &privateKey, &publicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
privateKeyOut.PublicKey.Point = publicKey[:]
|
||||
privateKeyOut.Secret = privateKey[:]
|
||||
return privateKeyOut, nil
|
||||
}
|
||||
|
||||
func generateKey(rand io.Reader, privateKey *x25519lib.Key, publicKey *x25519lib.Key) error {
|
||||
maxRounds := 10
|
||||
isZero := true
|
||||
for round := 0; isZero; round++ {
|
||||
if round == maxRounds {
|
||||
return errors.InvalidArgumentError("x25519: zero keys only, randomness source might be corrupt")
|
||||
}
|
||||
_, err := io.ReadFull(rand, privateKey[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
isZero = constantTimeIsZero(privateKey[:])
|
||||
}
|
||||
x25519lib.KeyGen(publicKey, privateKey)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encrypt encrypts a sessionKey with x25519 according to
|
||||
// the OpenPGP crypto refresh specification section 5.1.6. The function assumes that the
|
||||
// sessionKey has the correct format and padding according to the specification.
|
||||
func Encrypt(rand io.Reader, publicKey *PublicKey, sessionKey []byte) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, err error) {
|
||||
var ephemeralPrivate, ephemeralPublic, staticPublic, shared x25519lib.Key
|
||||
// Check that the input static public key has 32 bytes
|
||||
if len(publicKey.Point) != KeySize {
|
||||
err = errors.KeyInvalidError("x25519: the public key has the wrong size")
|
||||
return
|
||||
}
|
||||
copy(staticPublic[:], publicKey.Point)
|
||||
// Generate ephemeral keyPair
|
||||
err = generateKey(rand, &ephemeralPrivate, &ephemeralPublic)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Compute shared key
|
||||
ok := x25519lib.Shared(&shared, &ephemeralPrivate, &staticPublic)
|
||||
if !ok {
|
||||
err = errors.KeyInvalidError("x25519: the public key is a low order point")
|
||||
return
|
||||
}
|
||||
// Derive the encryption key from the shared secret
|
||||
encryptionKey := applyHKDF(ephemeralPublic[:], publicKey.Point[:], shared[:])
|
||||
ephemeralPublicKey = &PublicKey{
|
||||
Point: ephemeralPublic[:],
|
||||
}
|
||||
// Encrypt the sessionKey with aes key wrapping
|
||||
encryptedSessionKey, err = keywrap.Wrap(encryptionKey, sessionKey)
|
||||
return
|
||||
}
|
||||
|
||||
// Decrypt decrypts a session key stored in ciphertext with the provided x25519
|
||||
// private key and ephemeral public key.
|
||||
func Decrypt(privateKey *PrivateKey, ephemeralPublicKey *PublicKey, ciphertext []byte) (encodedSessionKey []byte, err error) {
|
||||
var ephemeralPublic, staticPrivate, shared x25519lib.Key
|
||||
// Check that the input ephemeral public key has 32 bytes
|
||||
if len(ephemeralPublicKey.Point) != KeySize {
|
||||
err = errors.KeyInvalidError("x25519: the public key has the wrong size")
|
||||
return
|
||||
}
|
||||
copy(ephemeralPublic[:], ephemeralPublicKey.Point)
|
||||
subtle.ConstantTimeCopy(1, staticPrivate[:], privateKey.Secret)
|
||||
// Compute shared key
|
||||
ok := x25519lib.Shared(&shared, &staticPrivate, &ephemeralPublic)
|
||||
if !ok {
|
||||
err = errors.KeyInvalidError("x25519: the ephemeral public key is a low order point")
|
||||
return
|
||||
}
|
||||
// Derive the encryption key from the shared secret
|
||||
encryptionKey := applyHKDF(ephemeralPublicKey.Point[:], privateKey.PublicKey.Point[:], shared[:])
|
||||
// Decrypt the session key with aes key wrapping
|
||||
encodedSessionKey, err = keywrap.Unwrap(encryptionKey, ciphertext)
|
||||
return
|
||||
}
|
||||
|
||||
func applyHKDF(ephemeralPublicKey []byte, publicKey []byte, sharedSecret []byte) []byte {
|
||||
inputKey := make([]byte, 3*KeySize)
|
||||
// ephemeral public key | recipient public key | shared secret
|
||||
subtle.ConstantTimeCopy(1, inputKey[:KeySize], ephemeralPublicKey)
|
||||
subtle.ConstantTimeCopy(1, inputKey[KeySize:2*KeySize], publicKey)
|
||||
subtle.ConstantTimeCopy(1, inputKey[2*KeySize:], sharedSecret)
|
||||
hkdfReader := hkdf.New(sha256.New, inputKey, []byte{}, []byte(hkdfInfo))
|
||||
encryptionKey := make([]byte, aes128KeySize)
|
||||
_, _ = io.ReadFull(hkdfReader, encryptionKey)
|
||||
return encryptionKey
|
||||
}
|
||||
|
||||
func constantTimeIsZero(bytes []byte) bool {
|
||||
isZero := byte(0)
|
||||
for _, b := range bytes {
|
||||
isZero |= b
|
||||
}
|
||||
return isZero == 0
|
||||
}
|
||||
|
||||
// ENCODING/DECODING ciphertexts:
|
||||
|
||||
// EncodeFieldsLength returns the length of the ciphertext encoding
|
||||
// given the encrypted session key.
|
||||
func EncodedFieldsLength(encryptedSessionKey []byte, v6 bool) int {
|
||||
lenCipherFunction := 0
|
||||
if !v6 {
|
||||
lenCipherFunction = 1
|
||||
}
|
||||
return KeySize + 1 + len(encryptedSessionKey) + lenCipherFunction
|
||||
}
|
||||
|
||||
// EncodeField encodes x25519 session key encryption fields as
|
||||
// ephemeral x25519 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey
|
||||
// and writes it to writer.
|
||||
func EncodeFields(writer io.Writer, ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, v6 bool) (err error) {
|
||||
lenAlgorithm := 0
|
||||
if !v6 {
|
||||
lenAlgorithm = 1
|
||||
}
|
||||
if _, err = writer.Write(ephemeralPublicKey.Point); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = writer.Write([]byte{byte(len(encryptedSessionKey) + lenAlgorithm)}); err != nil {
|
||||
return err
|
||||
}
|
||||
if !v6 {
|
||||
if _, err = writer.Write([]byte{cipherFunction}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err = writer.Write(encryptedSessionKey)
|
||||
return err
|
||||
}
|
||||
|
||||
// DecodeField decodes a x25519 session key encryption as
|
||||
// ephemeral x25519 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey.
|
||||
func DecodeFields(reader io.Reader, v6 bool) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, err error) {
|
||||
var buf [1]byte
|
||||
ephemeralPublicKey = &PublicKey{
|
||||
Point: make([]byte, KeySize),
|
||||
}
|
||||
// 32 octets representing an ephemeral x25519 public key.
|
||||
if _, err = io.ReadFull(reader, ephemeralPublicKey.Point); err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
// A one-octet size of the following fields.
|
||||
if _, err = io.ReadFull(reader, buf[:]); err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
followingLen := buf[0]
|
||||
// The one-octet algorithm identifier, if it was passed (in the case of a v3 PKESK packet).
|
||||
if !v6 {
|
||||
if _, err = io.ReadFull(reader, buf[:]); err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
cipherFunction = buf[0]
|
||||
followingLen -= 1
|
||||
}
|
||||
// The encrypted session key.
|
||||
encryptedSessionKey = make([]byte, followingLen)
|
||||
if _, err = io.ReadFull(reader, encryptedSessionKey); err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
return ephemeralPublicKey, encryptedSessionKey, cipherFunction, nil
|
||||
}
|
||||
229
vendor/github.com/ProtonMail/go-crypto/openpgp/x448/x448.go
generated
vendored
Normal file
229
vendor/github.com/ProtonMail/go-crypto/openpgp/x448/x448.go
generated
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
package x448
|
||||
|
||||
import (
|
||||
"crypto/sha512"
|
||||
"crypto/subtle"
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/aes/keywrap"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
x448lib "github.com/cloudflare/circl/dh/x448"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
)
|
||||
|
||||
const (
|
||||
hkdfInfo = "OpenPGP X448"
|
||||
aes256KeySize = 32
|
||||
// The size of a public or private key in bytes.
|
||||
KeySize = x448lib.Size
|
||||
)
|
||||
|
||||
type PublicKey struct {
|
||||
// Point represents the encoded elliptic curve point of the public key.
|
||||
Point []byte
|
||||
}
|
||||
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
// Secret represents the secret of the private key.
|
||||
Secret []byte
|
||||
}
|
||||
|
||||
// NewPrivateKey creates a new empty private key including the public key.
|
||||
func NewPrivateKey(key PublicKey) *PrivateKey {
|
||||
return &PrivateKey{
|
||||
PublicKey: key,
|
||||
}
|
||||
}
|
||||
|
||||
// Validate validates that the provided public key matches
|
||||
// the private key.
|
||||
func Validate(pk *PrivateKey) (err error) {
|
||||
var expectedPublicKey, privateKey x448lib.Key
|
||||
subtle.ConstantTimeCopy(1, privateKey[:], pk.Secret)
|
||||
x448lib.KeyGen(&expectedPublicKey, &privateKey)
|
||||
if subtle.ConstantTimeCompare(expectedPublicKey[:], pk.PublicKey.Point) == 0 {
|
||||
return errors.KeyInvalidError("x448: invalid key")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateKey generates a new x448 key pair.
|
||||
func GenerateKey(rand io.Reader) (*PrivateKey, error) {
|
||||
var privateKey, publicKey x448lib.Key
|
||||
privateKeyOut := new(PrivateKey)
|
||||
err := generateKey(rand, &privateKey, &publicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
privateKeyOut.PublicKey.Point = publicKey[:]
|
||||
privateKeyOut.Secret = privateKey[:]
|
||||
return privateKeyOut, nil
|
||||
}
|
||||
|
||||
func generateKey(rand io.Reader, privateKey *x448lib.Key, publicKey *x448lib.Key) error {
|
||||
maxRounds := 10
|
||||
isZero := true
|
||||
for round := 0; isZero; round++ {
|
||||
if round == maxRounds {
|
||||
return errors.InvalidArgumentError("x448: zero keys only, randomness source might be corrupt")
|
||||
}
|
||||
_, err := io.ReadFull(rand, privateKey[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
isZero = constantTimeIsZero(privateKey[:])
|
||||
}
|
||||
x448lib.KeyGen(publicKey, privateKey)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encrypt encrypts a sessionKey with x448 according to
|
||||
// the OpenPGP crypto refresh specification section 5.1.7. The function assumes that the
|
||||
// sessionKey has the correct format and padding according to the specification.
|
||||
func Encrypt(rand io.Reader, publicKey *PublicKey, sessionKey []byte) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, err error) {
|
||||
var ephemeralPrivate, ephemeralPublic, staticPublic, shared x448lib.Key
|
||||
// Check that the input static public key has 56 bytes.
|
||||
if len(publicKey.Point) != KeySize {
|
||||
err = errors.KeyInvalidError("x448: the public key has the wrong size")
|
||||
return nil, nil, err
|
||||
}
|
||||
copy(staticPublic[:], publicKey.Point)
|
||||
// Generate ephemeral keyPair.
|
||||
if err = generateKey(rand, &ephemeralPrivate, &ephemeralPublic); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Compute shared key.
|
||||
ok := x448lib.Shared(&shared, &ephemeralPrivate, &staticPublic)
|
||||
if !ok {
|
||||
err = errors.KeyInvalidError("x448: the public key is a low order point")
|
||||
return nil, nil, err
|
||||
}
|
||||
// Derive the encryption key from the shared secret.
|
||||
encryptionKey := applyHKDF(ephemeralPublic[:], publicKey.Point[:], shared[:])
|
||||
ephemeralPublicKey = &PublicKey{
|
||||
Point: ephemeralPublic[:],
|
||||
}
|
||||
// Encrypt the sessionKey with aes key wrapping.
|
||||
encryptedSessionKey, err = keywrap.Wrap(encryptionKey, sessionKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return ephemeralPublicKey, encryptedSessionKey, nil
|
||||
}
|
||||
|
||||
// Decrypt decrypts a session key stored in ciphertext with the provided x448
|
||||
// private key and ephemeral public key.
|
||||
func Decrypt(privateKey *PrivateKey, ephemeralPublicKey *PublicKey, ciphertext []byte) (encodedSessionKey []byte, err error) {
|
||||
var ephemeralPublic, staticPrivate, shared x448lib.Key
|
||||
// Check that the input ephemeral public key has 56 bytes.
|
||||
if len(ephemeralPublicKey.Point) != KeySize {
|
||||
err = errors.KeyInvalidError("x448: the public key has the wrong size")
|
||||
return nil, err
|
||||
}
|
||||
copy(ephemeralPublic[:], ephemeralPublicKey.Point)
|
||||
subtle.ConstantTimeCopy(1, staticPrivate[:], privateKey.Secret)
|
||||
// Compute shared key.
|
||||
ok := x448lib.Shared(&shared, &staticPrivate, &ephemeralPublic)
|
||||
if !ok {
|
||||
err = errors.KeyInvalidError("x448: the ephemeral public key is a low order point")
|
||||
return nil, err
|
||||
}
|
||||
// Derive the encryption key from the shared secret.
|
||||
encryptionKey := applyHKDF(ephemeralPublicKey.Point[:], privateKey.PublicKey.Point[:], shared[:])
|
||||
// Decrypt the session key with aes key wrapping.
|
||||
encodedSessionKey, err = keywrap.Unwrap(encryptionKey, ciphertext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodedSessionKey, nil
|
||||
}
|
||||
|
||||
func applyHKDF(ephemeralPublicKey []byte, publicKey []byte, sharedSecret []byte) []byte {
|
||||
inputKey := make([]byte, 3*KeySize)
|
||||
// ephemeral public key | recipient public key | shared secret.
|
||||
subtle.ConstantTimeCopy(1, inputKey[:KeySize], ephemeralPublicKey)
|
||||
subtle.ConstantTimeCopy(1, inputKey[KeySize:2*KeySize], publicKey)
|
||||
subtle.ConstantTimeCopy(1, inputKey[2*KeySize:], sharedSecret)
|
||||
hkdfReader := hkdf.New(sha512.New, inputKey, []byte{}, []byte(hkdfInfo))
|
||||
encryptionKey := make([]byte, aes256KeySize)
|
||||
_, _ = io.ReadFull(hkdfReader, encryptionKey)
|
||||
return encryptionKey
|
||||
}
|
||||
|
||||
func constantTimeIsZero(bytes []byte) bool {
|
||||
isZero := byte(0)
|
||||
for _, b := range bytes {
|
||||
isZero |= b
|
||||
}
|
||||
return isZero == 0
|
||||
}
|
||||
|
||||
// ENCODING/DECODING ciphertexts:
|
||||
|
||||
// EncodeFieldsLength returns the length of the ciphertext encoding
|
||||
// given the encrypted session key.
|
||||
func EncodedFieldsLength(encryptedSessionKey []byte, v6 bool) int {
|
||||
lenCipherFunction := 0
|
||||
if !v6 {
|
||||
lenCipherFunction = 1
|
||||
}
|
||||
return KeySize + 1 + len(encryptedSessionKey) + lenCipherFunction
|
||||
}
|
||||
|
||||
// EncodeField encodes x448 session key encryption fields as
|
||||
// ephemeral x448 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey
|
||||
// and writes it to writer.
|
||||
func EncodeFields(writer io.Writer, ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, v6 bool) (err error) {
|
||||
lenAlgorithm := 0
|
||||
if !v6 {
|
||||
lenAlgorithm = 1
|
||||
}
|
||||
if _, err = writer.Write(ephemeralPublicKey.Point); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = writer.Write([]byte{byte(len(encryptedSessionKey) + lenAlgorithm)}); err != nil {
|
||||
return err
|
||||
}
|
||||
if !v6 {
|
||||
if _, err = writer.Write([]byte{cipherFunction}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err = writer.Write(encryptedSessionKey); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DecodeField decodes a x448 session key encryption as
|
||||
// ephemeral x448 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey.
|
||||
func DecodeFields(reader io.Reader, v6 bool) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, err error) {
|
||||
var buf [1]byte
|
||||
ephemeralPublicKey = &PublicKey{
|
||||
Point: make([]byte, KeySize),
|
||||
}
|
||||
// 56 octets representing an ephemeral x448 public key.
|
||||
if _, err = io.ReadFull(reader, ephemeralPublicKey.Point); err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
// A one-octet size of the following fields.
|
||||
if _, err = io.ReadFull(reader, buf[:]); err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
followingLen := buf[0]
|
||||
// The one-octet algorithm identifier, if it was passed (in the case of a v3 PKESK packet).
|
||||
if !v6 {
|
||||
if _, err = io.ReadFull(reader, buf[:]); err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
cipherFunction = buf[0]
|
||||
followingLen -= 1
|
||||
}
|
||||
// The encrypted session key.
|
||||
encryptedSessionKey = make([]byte, followingLen)
|
||||
if _, err = io.ReadFull(reader, encryptedSessionKey); err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
return ephemeralPublicKey, encryptedSessionKey, cipherFunction, nil
|
||||
}
|
||||
4
vendor/github.com/alecthomas/chroma/v2/.editorconfig
generated
vendored
4
vendor/github.com/alecthomas/chroma/v2/.editorconfig
generated
vendored
@@ -11,3 +11,7 @@ insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = false
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
3
vendor/github.com/alecthomas/chroma/v2/.gitignore
generated
vendored
3
vendor/github.com/alecthomas/chroma/v2/.gitignore
generated
vendored
@@ -23,3 +23,6 @@ _models/
|
||||
_examples/
|
||||
*.min.*
|
||||
build/
|
||||
|
||||
cmd/chromad/static/chroma.wasm
|
||||
cmd/chromad/static/wasm_exec.js
|
||||
|
||||
21
vendor/github.com/alecthomas/chroma/v2/.golangci.yml
generated
vendored
21
vendor/github.com/alecthomas/chroma/v2/.golangci.yml
generated
vendored
@@ -1,7 +1,5 @@
|
||||
run:
|
||||
tests: true
|
||||
skip-dirs:
|
||||
- _examples
|
||||
|
||||
output:
|
||||
print-issued-lines: false
|
||||
@@ -9,8 +7,6 @@ output:
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- maligned
|
||||
- megacheck
|
||||
- lll
|
||||
- gocyclo
|
||||
- dupl
|
||||
@@ -18,9 +14,7 @@ linters:
|
||||
- funlen
|
||||
- godox
|
||||
- wsl
|
||||
- gomnd
|
||||
- gocognit
|
||||
- goerr113
|
||||
- nolintlint
|
||||
- testpackage
|
||||
- godot
|
||||
@@ -28,12 +22,10 @@ linters:
|
||||
- paralleltest
|
||||
- nlreturn
|
||||
- cyclop
|
||||
- exhaustivestruct
|
||||
- gci
|
||||
- gofumpt
|
||||
- errorlint
|
||||
- exhaustive
|
||||
- ifshort
|
||||
- wrapcheck
|
||||
- stylecheck
|
||||
- thelper
|
||||
@@ -46,13 +38,18 @@ linters:
|
||||
- ireturn
|
||||
- maintidx
|
||||
- govet
|
||||
- nosnakecase
|
||||
- testableexamples
|
||||
- musttag
|
||||
- depguard
|
||||
- goconst
|
||||
- perfsprint
|
||||
- mnd
|
||||
- predeclared
|
||||
- recvcheck
|
||||
- tenv
|
||||
- err113
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: true
|
||||
gocyclo:
|
||||
min-complexity: 10
|
||||
dupl:
|
||||
@@ -67,6 +64,8 @@ linters-settings:
|
||||
|
||||
|
||||
issues:
|
||||
exclude-dirs:
|
||||
- _examples
|
||||
max-per-linter: 0
|
||||
max-same: 0
|
||||
exclude-use-default: false
|
||||
|
||||
11
vendor/github.com/alecthomas/chroma/v2/.goreleaser.yml
generated
vendored
11
vendor/github.com/alecthomas/chroma/v2/.goreleaser.yml
generated
vendored
@@ -4,8 +4,7 @@ release:
|
||||
owner: alecthomas
|
||||
name: chroma
|
||||
brews:
|
||||
-
|
||||
install: bin.install "chroma"
|
||||
- install: bin.install "chroma"
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
builds:
|
||||
@@ -24,14 +23,12 @@ builds:
|
||||
ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}
|
||||
binary: chroma
|
||||
archives:
|
||||
-
|
||||
format: tar.gz
|
||||
name_template: '{{ .Binary }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{
|
||||
.Arm }}{{ end }}'
|
||||
- format: tar.gz
|
||||
name_template: "{{ .Binary }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||
files:
|
||||
- COPYING
|
||||
- README*
|
||||
snapshot:
|
||||
name_template: SNAPSHOT-{{ .Commit }}
|
||||
checksum:
|
||||
name_template: '{{ .ProjectName }}-{{ .Version }}-checksums.txt'
|
||||
name_template: "{{ .ProjectName }}-{{ .Version }}-checksums.txt"
|
||||
|
||||
11
vendor/github.com/alecthomas/chroma/v2/AGENTS.md
generated
vendored
Normal file
11
vendor/github.com/alecthomas/chroma/v2/AGENTS.md
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
Chroma is a syntax highlighting library, tool and web playground for Go. It is based on Pygments and includes importers for it, so most of the same concepts from Pygments apply to Chroma.
|
||||
|
||||
This project is written in Go, uses Hermit to manage tooling, and Just for helper commands. Helper scripts are in ./scripts.
|
||||
|
||||
Language definitions are XML files defined in ./lexers/embedded/*.xml.
|
||||
|
||||
Styles/themes are defined in ./styles/*.xml.
|
||||
|
||||
The CLI can be run with `chroma`.
|
||||
|
||||
The web playground can be run with `chromad --csrf-key=moo`. It blocks, so should generally be run in the background. It also does not hot reload, so has to be manually restarted. The playground has two modes - for local development it uses the server itself to render, while for production running `just chromad` will compile ./cmd/libchromawasm into a WASM module that is bundled into `chromad`.
|
||||
64
vendor/github.com/alecthomas/chroma/v2/Dockerfile
generated
vendored
Normal file
64
vendor/github.com/alecthomas/chroma/v2/Dockerfile
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
# Multi-stage Dockerfile for chromad Go application using Hermit-managed tools
|
||||
|
||||
# Build stage
|
||||
FROM ubuntu:24.04 AS builder
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl \
|
||||
git \
|
||||
ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the entire project (including bin directory with Hermit tools)
|
||||
COPY . .
|
||||
|
||||
# Make Hermit tools executable and add to PATH
|
||||
ENV PATH="/app/bin:${PATH}"
|
||||
|
||||
# Set Go environment variables for static compilation
|
||||
ENV CGO_ENABLED=0
|
||||
ENV GOOS=linux
|
||||
ENV GOARCH=amd64
|
||||
|
||||
# Build the application using just
|
||||
RUN just chromad
|
||||
|
||||
# Runtime stage
|
||||
FROM alpine:3.23 AS runtime
|
||||
|
||||
# Install ca-certificates for HTTPS requests
|
||||
RUN apk --no-cache add ca-certificates curl
|
||||
|
||||
# Create a non-root user
|
||||
RUN addgroup -g 1001 chromad && \
|
||||
adduser -D -s /bin/sh -u 1001 -G chromad chromad
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the binary from build stage
|
||||
COPY --from=builder /app/build/chromad /app/chromad
|
||||
|
||||
# Change ownership to non-root user
|
||||
RUN chown chromad:chromad /app/chromad
|
||||
|
||||
# Switch to non-root user
|
||||
USER chromad
|
||||
|
||||
# Expose port (default is 8080, but can be overridden via PORT env var)
|
||||
EXPOSE 8080
|
||||
|
||||
# Set default environment variables
|
||||
ENV PORT=8080
|
||||
ENV CHROMA_CSRF_KEY="testtest"
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD curl -fsSL http://127.0.0.1:8080/ > /dev/null
|
||||
|
||||
# Run the application
|
||||
CMD ["sh", "-c", "./chromad --csrf-key=$CHROMA_CSRF_KEY --bind=0.0.0.0:$PORT"]
|
||||
55
vendor/github.com/alecthomas/chroma/v2/Justfile
generated
vendored
Normal file
55
vendor/github.com/alecthomas/chroma/v2/Justfile
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
set positional-arguments := true
|
||||
set shell := ["bash", "-c"]
|
||||
|
||||
version := `git describe --tags --dirty --always`
|
||||
export GOOS := env("GOOS", "linux")
|
||||
export GOARCH := env("GOARCH", "amd64")
|
||||
|
||||
_help:
|
||||
@just -l
|
||||
|
||||
# Generate README.md from lexer definitions
|
||||
readme:
|
||||
#!/usr/bin/env bash
|
||||
GOOS= GOARCH= ./table.py
|
||||
|
||||
# Generate tokentype_string.go
|
||||
tokentype-string:
|
||||
go generate
|
||||
|
||||
# Format JavaScript files
|
||||
format-js:
|
||||
biome format --write cmd/chromad/static/index.js cmd/chromad/static/chroma.js
|
||||
|
||||
# Build chromad binary
|
||||
chromad: wasm-exec chroma-wasm
|
||||
#!/usr/bin/env bash
|
||||
rm -rf build
|
||||
mk cmd/chromad/static/index.min.js : cmd/chromad/static/{index,chroma}.js -- \
|
||||
esbuild --platform=browser --format=esm --bundle cmd/chromad/static/index.js --minify --external:./wasm_exec.js --outfile=cmd/chromad/static/index.min.js
|
||||
mk cmd/chromad/static/index.min.css : cmd/chromad/static/index.css -- \
|
||||
esbuild --bundle cmd/chromad/static/index.css --minify --outfile=cmd/chromad/static/index.min.css
|
||||
cd cmd/chromad && CGOENABLED=0 go build -ldflags="-X 'main.version={{ version }}'" -o ../../build/chromad .
|
||||
|
||||
# Copy wasm_exec.js from TinyGo
|
||||
wasm-exec:
|
||||
#!/usr/bin/env bash
|
||||
tinygoroot=$(tinygo env TINYGOROOT)
|
||||
mk cmd/chromad/static/wasm_exec.js : "$tinygoroot/targets/wasm_exec.js" -- \
|
||||
install -m644 "$tinygoroot/targets/wasm_exec.js" cmd/chromad/static/wasm_exec.js
|
||||
|
||||
# Build WASM binary
|
||||
chroma-wasm:
|
||||
#!/usr/bin/env bash
|
||||
if type tinygo > /dev/null 2>&1; then
|
||||
mk cmd/chromad/static/chroma.wasm : cmd/libchromawasm/main.go -- \
|
||||
tinygo build -no-debug -target wasm -o cmd/chromad/static/chroma.wasm cmd/libchromawasm/main.go
|
||||
else
|
||||
mk cmd/chromad/static/chroma.wasm : cmd/libchromawasm/main.go -- \
|
||||
GOOS=js GOARCH=wasm go build -o cmd/chromad/static/chroma.wasm cmd/libchromawasm/main.go
|
||||
fi
|
||||
|
||||
# Upload chromad to server
|
||||
upload: chromad
|
||||
scp build/chromad root@swapoff.org:
|
||||
ssh root@swapoff.org 'install -m755 ./chromad /srv/http/swapoff.org/bin && service chromad restart'
|
||||
23
vendor/github.com/alecthomas/chroma/v2/Makefile
generated
vendored
23
vendor/github.com/alecthomas/chroma/v2/Makefile
generated
vendored
@@ -1,23 +0,0 @@
|
||||
.PHONY: chromad upload all
|
||||
|
||||
VERSION ?= $(shell git describe --tags --dirty --always)
|
||||
export GOOS ?= linux
|
||||
export GOARCH ?= amd64
|
||||
|
||||
all: README.md tokentype_string.go
|
||||
|
||||
README.md: lexers/*/*.go
|
||||
./table.py
|
||||
|
||||
tokentype_string.go: types.go
|
||||
go generate
|
||||
|
||||
chromad:
|
||||
rm -rf build
|
||||
esbuild --bundle cmd/chromad/static/index.js --minify --outfile=cmd/chromad/static/index.min.js
|
||||
esbuild --bundle cmd/chromad/static/index.css --minify --outfile=cmd/chromad/static/index.min.css
|
||||
(export CGOENABLED=0 ; cd ./cmd/chromad && go build -ldflags="-X 'main.version=$(VERSION)'" -o ../../build/chromad .)
|
||||
|
||||
upload: build/chromad
|
||||
scp build/chromad root@swapoff.org: && \
|
||||
ssh root@swapoff.org 'install -m755 ./chromad /srv/http/swapoff.org/bin && service chromad restart'
|
||||
123
vendor/github.com/alecthomas/chroma/v2/README.md
generated
vendored
123
vendor/github.com/alecthomas/chroma/v2/README.md
generated
vendored
@@ -1,6 +1,9 @@
|
||||
# Chroma — A general purpose syntax highlighter in pure Go
|
||||

|
||||
|
||||
# A general purpose syntax highlighter in pure Go
|
||||
|
||||
[](https://pkg.go.dev/github.com/alecthomas/chroma/v2) [](https://github.com/alecthomas/chroma/actions/workflows/ci.yml) [](https://invite.slack.golangbridge.org/)
|
||||
|
||||
[](https://godoc.org/github.com/alecthomas/chroma) [](https://github.com/alecthomas/chroma/actions/workflows/ci.yml) [](https://invite.slack.golangbridge.org/)
|
||||
|
||||
Chroma takes source code and other structured text and converts it into syntax
|
||||
highlighted HTML, ANSI-coloured text, etc.
|
||||
@@ -8,75 +11,73 @@ highlighted HTML, ANSI-coloured text, etc.
|
||||
Chroma is based heavily on [Pygments](http://pygments.org/), and includes
|
||||
translators for Pygments lexers and styles.
|
||||
|
||||
<a id="markdown-table-of-contents" name="table-of-contents"></a>
|
||||
|
||||
## Table of Contents
|
||||
|
||||
<!-- TOC -->
|
||||
|
||||
1. [Table of Contents](#table-of-contents)
|
||||
2. [Supported languages](#supported-languages)
|
||||
3. [Try it](#try-it)
|
||||
4. [Using the library](#using-the-library)
|
||||
1. [Supported languages](#supported-languages)
|
||||
2. [Try it](#try-it)
|
||||
3. [Using the library](#using-the-library)
|
||||
1. [Quick start](#quick-start)
|
||||
2. [Identifying the language](#identifying-the-language)
|
||||
3. [Formatting the output](#formatting-the-output)
|
||||
4. [The HTML formatter](#the-html-formatter)
|
||||
5. [More detail](#more-detail)
|
||||
4. [More detail](#more-detail)
|
||||
1. [Lexers](#lexers)
|
||||
2. [Formatters](#formatters)
|
||||
3. [Styles](#styles)
|
||||
6. [Command-line interface](#command-line-interface)
|
||||
7. [Testing lexers](#testing-lexers)
|
||||
8. [What's missing compared to Pygments?](#whats-missing-compared-to-pygments)
|
||||
5. [Command-line interface](#command-line-interface)
|
||||
6. [Testing lexers](#testing-lexers)
|
||||
7. [What's missing compared to Pygments?](#whats-missing-compared-to-pygments)
|
||||
|
||||
<!-- /TOC -->
|
||||
|
||||
<a id="markdown-supported-languages" name="supported-languages"></a>
|
||||
|
||||
## Supported languages
|
||||
|
||||
| Prefix | Language |
|
||||
| :----: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Agda, AL, Alloy, Angular2, ANTLR, ApacheConf, APL, AppleScript, ArangoDB AQL, Arduino, ArmAsm, AutoHotkey, AutoIt, Awk |
|
||||
| B | Ballerina, Bash, Bash Session, Batchfile, BibTeX, Bicep, BlitzBasic, BNF, BQN, Brainfuck |
|
||||
| C | C, C#, C++, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Chapel, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython |
|
||||
| D | D, Dart, Dax, Diff, Django/Jinja, dns, Docker, DTD, Dylan |
|
||||
| E | EBNF, Elixir, Elm, EmacsLisp, Erlang |
|
||||
| F | Factor, Fennel, Fish, Forth, Fortran, FortranFixed, FSharp |
|
||||
| G | GAS, GDScript, Genshi, Genshi HTML, Genshi Text, Gherkin, GLSL, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groff, Groovy |
|
||||
| H | Handlebars, Hare, Haskell, Haxe, HCL, Hexdump, HLB, HLSL, HolyC, HTML, HTTP, Hy |
|
||||
| I | Idris, Igor, INI, Io, ISCdhcpd |
|
||||
| J | J, Java, JavaScript, JSON, Julia, Jungle |
|
||||
| K | Kotlin |
|
||||
| L | Lighttpd configuration file, LLVM, Lua |
|
||||
| M | Makefile, Mako, markdown, Mason, Mathematica, Matlab, mcfunction, Meson, Metal, MiniZinc, MLIR, Modula-2, MonkeyC, MorrowindScript, Myghty, MySQL |
|
||||
| N | NASM, Natural, Newspeak, Nginx configuration file, Nim, Nix |
|
||||
| O | Objective-C, OCaml, Octave, Odin, OnesEnterprise, OpenEdge ABL, OpenSCAD, Org Mode |
|
||||
| P | PacmanConf, Perl, PHP, PHTML, Pig, PkgConfig, PL/pgSQL, plaintext, Plutus Core, Pony, PostgreSQL SQL dialect, PostScript, POVRay, PowerQuery, PowerShell, Prolog, PromQL, properties, Protocol Buffer, PRQL, PSL, Puppet, Python, Python 2 |
|
||||
| Q | QBasic, QML |
|
||||
| R | R, Racket, Ragel, Raku, react, ReasonML, reg, reStructuredText, Rexx, Ruby, Rust |
|
||||
| S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Sed, Sieve, Smali, Smalltalk, Smarty, Snobol, Solidity, SourcePawn, SPARQL, SQL, SquidConf, Standard ML, stas, Stylus, Svelte, Swift, SYSTEMD, systemverilog |
|
||||
| T | TableGen, Tal, TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData |
|
||||
| V | V, V shell, Vala, VB.net, verilog, VHDL, VHS, VimL, vue |
|
||||
| W | WDTE, WebGPU Shading Language, Whiley |
|
||||
| X | XML, Xorg |
|
||||
| Y | YAML, YANG |
|
||||
| Z | Z80 Assembly, Zed, Zig |
|
||||
| Prefix | Language
|
||||
| :----: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
| A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Agda, AL, Alloy, Angular2, ANTLR, ApacheConf, APL, AppleScript, ArangoDB AQL, Arduino, ArmAsm, ATL, AutoHotkey, AutoIt, Awk
|
||||
| B | Ballerina, Bash, Bash Session, Batchfile, Beef, BibTeX, Bicep, BlitzBasic, BNF, BQN, Brainfuck
|
||||
| C | C, C#, C++, C3, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Chapel, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Core, Crystal, CSS, CSV, CUE, Cython
|
||||
| D | D, Dart, Dax, Desktop file, Diff, Django/Jinja, dns, Docker, DTD, Dylan
|
||||
| E | EBNF, Elixir, Elm, EmacsLisp, Erlang
|
||||
| F | Factor, Fennel, Fish, Forth, Fortran, FortranFixed, FSharp
|
||||
| G | GAS, GDScript, GDScript3, Gemtext, Genshi, Genshi HTML, Genshi Text, Gherkin, Gleam, GLSL, Gnuplot, Go, Go HTML Template, Go Template, Go Text Template, GraphQL, Groff, Groovy
|
||||
| H | Handlebars, Hare, Haskell, Haxe, HCL, Hexdump, HLB, HLSL, HolyC, HTML, HTTP, Hy
|
||||
| I | Idris, Igor, INI, Io, ISCdhcpd
|
||||
| J | J, Janet, Java, JavaScript, JSON, JSONata, Jsonnet, Julia, Jungle
|
||||
| K | Kakoune, Kotlin
|
||||
| L | Lean4, Lighttpd configuration file, LLVM, lox, Lua
|
||||
| M | Makefile, Mako, markdown, Markless, Mason, Materialize SQL dialect, Mathematica, Matlab, MCFunction, Meson, Metal, MiniZinc, MLIR, Modelica, Modula-2, Mojo, MonkeyC, MoonScript, MorrowindScript, Myghty, MySQL
|
||||
| N | NASM, Natural, NDISASM, Newspeak, Nginx configuration file, Nim, Nix, NSIS, Nu
|
||||
| O | Objective-C, ObjectPascal, OCaml, Octave, Odin, OnesEnterprise, OpenEdge ABL, OpenSCAD, Org Mode
|
||||
| P | PacmanConf, Perl, PHP, PHTML, Pig, PkgConfig, PL/pgSQL, plaintext, Plutus Core, Pony, PostgreSQL SQL dialect, PostScript, POVRay, PowerQuery, PowerShell, Prolog, Promela, PromQL, properties, Protocol Buffer, Protocol Buffer Text Format, PRQL, PSL, Puppet, Python, Python 2
|
||||
| Q | QBasic, QML
|
||||
| R | R, Racket, Ragel, Raku, react, ReasonML, reg, Rego, reStructuredText, Rexx, RGBDS Assembly, Ring, RPGLE, RPMSpec, Ruby, Rust
|
||||
| S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Sed, Sieve, Smali, Smalltalk, Smarty, SNBT, Snobol, Solidity, SourcePawn, SPARQL, SQL, SquidConf, Standard ML, stas, Stylus, Svelte, Swift, SYSTEMD, systemverilog
|
||||
| T | TableGen, Tal, TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData, Typst
|
||||
| U | ucode
|
||||
| V | V, V shell, Vala, VB.net, verilog, VHDL, VHS, VimL, vue
|
||||
| W | WDTE, WebAssembly Text Format, WebGPU Shading Language, WebVTT, Whiley
|
||||
| X | XML, Xorg
|
||||
| Y | YAML, YANG
|
||||
| Z | Z80 Assembly, Zed, Zig
|
||||
|
||||
_I will attempt to keep this section up to date, but an authoritative list can be
|
||||
displayed with `chroma --list`._
|
||||
|
||||
<a id="markdown-try-it" name="try-it"></a>
|
||||
|
||||
## Try it
|
||||
|
||||
Try out various languages and styles on the [Chroma Playground](https://swapoff.org/chroma/playground/).
|
||||
|
||||
<a id="markdown-using-the-library" name="using-the-library"></a>
|
||||
|
||||
## Using the library
|
||||
|
||||
This is version 2 of Chroma, use the import path:
|
||||
|
||||
```go
|
||||
import "github.com/alecthomas/chroma/v2"
|
||||
```
|
||||
|
||||
Chroma, like Pygments, has the concepts of
|
||||
[lexers](https://github.com/alecthomas/chroma/tree/master/lexers),
|
||||
[formatters](https://github.com/alecthomas/chroma/tree/master/formatters) and
|
||||
@@ -95,8 +96,6 @@ In all cases, if a lexer, formatter or style can not be determined, `nil` will
|
||||
be returned. In this situation you may want to default to the `Fallback`
|
||||
value in each respective package, which provides sane defaults.
|
||||
|
||||
<a id="markdown-quick-start" name="quick-start"></a>
|
||||
|
||||
### Quick start
|
||||
|
||||
A convenience function exists that can be used to simply format some source
|
||||
@@ -106,8 +105,6 @@ text, without any effort:
|
||||
err := quick.Highlight(os.Stdout, someSourceCode, "go", "html", "monokai")
|
||||
```
|
||||
|
||||
<a id="markdown-identifying-the-language" name="identifying-the-language"></a>
|
||||
|
||||
### Identifying the language
|
||||
|
||||
To highlight code, you'll first have to identify what language the code is
|
||||
@@ -147,8 +144,6 @@ token types into a single token:
|
||||
lexer = chroma.Coalesce(lexer)
|
||||
```
|
||||
|
||||
<a id="markdown-formatting-the-output" name="formatting-the-output"></a>
|
||||
|
||||
### Formatting the output
|
||||
|
||||
Once a language is identified you will need to pick a formatter and a style (theme).
|
||||
@@ -177,8 +172,6 @@ And finally, format the tokens from the iterator:
|
||||
err := formatter.Format(w, style, iterator)
|
||||
```
|
||||
|
||||
<a id="markdown-the-html-formatter" name="the-html-formatter"></a>
|
||||
|
||||
### The HTML formatter
|
||||
|
||||
By default the `html` registered formatter generates standalone HTML with
|
||||
@@ -203,12 +196,8 @@ formatter := html.New(html.WithClasses(true))
|
||||
err := formatter.WriteCSS(w, style)
|
||||
```
|
||||
|
||||
<a id="markdown-more-detail" name="more-detail"></a>
|
||||
|
||||
## More detail
|
||||
|
||||
<a id="markdown-lexers" name="lexers"></a>
|
||||
|
||||
### Lexers
|
||||
|
||||
See the [Pygments documentation](http://pygments.org/docs/lexerdevelopment/)
|
||||
@@ -220,15 +209,12 @@ using the included Python 3 script `pygments2chroma_xml.py`. I use something lik
|
||||
the following:
|
||||
|
||||
```sh
|
||||
python3 _tools/pygments2chroma_xml.py \
|
||||
uv run --script _tools/pygments2chroma_xml.py \
|
||||
pygments.lexers.jvm.KotlinLexer \
|
||||
> lexers/embedded/kotlin.xml
|
||||
```
|
||||
|
||||
See notes in [pygments-lexers.txt](https://github.com/alecthomas/chroma/blob/master/pygments-lexers.txt)
|
||||
for a list of lexers, and notes on some of the issues importing them.
|
||||
|
||||
<a id="markdown-formatters" name="formatters"></a>
|
||||
A list of all lexers available in Pygments can be found in [pygments-lexers.txt](https://github.com/alecthomas/chroma/blob/master/pygments-lexers.txt).
|
||||
|
||||
### Formatters
|
||||
|
||||
@@ -237,8 +223,6 @@ Chroma supports HTML output, as well as terminal output in 8 colour, 256 colour,
|
||||
A `noop` formatter is included that outputs the token text only, and a `tokens`
|
||||
formatter outputs raw tokens. The latter is useful for debugging lexers.
|
||||
|
||||
<a id="markdown-styles" name="styles"></a>
|
||||
|
||||
### Styles
|
||||
|
||||
Chroma styles are defined in XML. The style entries use the
|
||||
@@ -262,8 +246,6 @@ Also, token types in a style file are hierarchical. For instance, when `CommentS
|
||||
|
||||
For a quick overview of the available styles and how they look, check out the [Chroma Style Gallery](https://xyproto.github.io/splash/docs/).
|
||||
|
||||
<a id="markdown-command-line-interface" name="command-line-interface"></a>
|
||||
|
||||
## Command-line interface
|
||||
|
||||
A command-line interface to Chroma is included.
|
||||
@@ -288,16 +270,19 @@ on under the hood for easy integration with [lesspipe shipping with
|
||||
Debian and derivatives](https://manpages.debian.org/lesspipe#USER_DEFINED_FILTERS);
|
||||
for that setup the `chroma` executable can be just symlinked to `~/.lessfilter`.
|
||||
|
||||
<a id="markdown-whats-missing-compared-to-pygments" name="whats-missing-compared-to-pygments"></a>
|
||||
## Projects using Chroma
|
||||
|
||||
<a id="markdown-testing-lexers" name="testing-lexers"></a>
|
||||
* [`moor`](https://github.com/walles/moor) is a full-blown pager that colorizes
|
||||
its input using Chroma
|
||||
* [Hugo](https://gohugo.io/) is a static site generator that [uses Chroma for syntax
|
||||
highlighting code examples](https://gohugo.io/content-management/syntax-highlighting/)
|
||||
|
||||
## Testing lexers
|
||||
|
||||
If you edit some lexers and want to try it, open a shell in `cmd/chromad` and run:
|
||||
|
||||
```shell
|
||||
go run .
|
||||
go run . --csrf-key=securekey
|
||||
```
|
||||
|
||||
A Link will be printed. Open it in your Browser. Now you can test on the Playground with your local changes.
|
||||
|
||||
6
vendor/github.com/alecthomas/chroma/v2/biome.json
generated
vendored
Normal file
6
vendor/github.com/alecthomas/chroma/v2/biome.json
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.0.5/schema.json",
|
||||
"formatter": {
|
||||
"indentStyle": "space"
|
||||
}
|
||||
}
|
||||
BIN
vendor/github.com/alecthomas/chroma/v2/chroma.jpg
generated
vendored
Normal file
BIN
vendor/github.com/alecthomas/chroma/v2/chroma.jpg
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
8
vendor/github.com/alecthomas/chroma/v2/colour.go
generated
vendored
8
vendor/github.com/alecthomas/chroma/v2/colour.go
generated
vendored
@@ -141,7 +141,7 @@ func ParseColour(colour string) Colour {
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return Colour(n + 1)
|
||||
return Colour(n + 1) //nolint:gosec
|
||||
}
|
||||
|
||||
// MustParseColour is like ParseColour except it panics if the colour is invalid.
|
||||
@@ -162,13 +162,13 @@ func (c Colour) String() string { return fmt.Sprintf("#%06x", int(c-1)) }
|
||||
func (c Colour) GoString() string { return fmt.Sprintf("Colour(0x%06x)", int(c-1)) }
|
||||
|
||||
// Red component of colour.
|
||||
func (c Colour) Red() uint8 { return uint8(((c - 1) >> 16) & 0xff) }
|
||||
func (c Colour) Red() uint8 { return uint8(((c - 1) >> 16) & 0xff) } //nolint:gosec
|
||||
|
||||
// Green component of colour.
|
||||
func (c Colour) Green() uint8 { return uint8(((c - 1) >> 8) & 0xff) }
|
||||
func (c Colour) Green() uint8 { return uint8(((c - 1) >> 8) & 0xff) } //nolint:gosec
|
||||
|
||||
// Blue component of colour.
|
||||
func (c Colour) Blue() uint8 { return uint8((c - 1) & 0xff) }
|
||||
func (c Colour) Blue() uint8 { return uint8((c - 1) & 0xff) } //nolint:gosec
|
||||
|
||||
// Colours is an orderable set of colours.
|
||||
type Colours []Colour
|
||||
|
||||
9
vendor/github.com/alecthomas/chroma/v2/delegate.go
generated
vendored
9
vendor/github.com/alecthomas/chroma/v2/delegate.go
generated
vendored
@@ -24,6 +24,15 @@ func DelegatingLexer(root Lexer, language Lexer) Lexer {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *delegatingLexer) SetTracing(enable bool) {
|
||||
if l, ok := d.language.(TracingLexer); ok {
|
||||
l.SetTracing(enable)
|
||||
}
|
||||
if l, ok := d.root.(TracingLexer); ok {
|
||||
l.SetTracing(enable)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *delegatingLexer) AnalyseText(text string) float32 {
|
||||
return d.root.AnalyseText(text)
|
||||
}
|
||||
|
||||
15
vendor/github.com/alecthomas/chroma/v2/emitters.go
generated
vendored
15
vendor/github.com/alecthomas/chroma/v2/emitters.go
generated
vendored
@@ -10,6 +10,12 @@ type Emitter interface {
|
||||
Emit(groups []string, state *LexerState) Iterator
|
||||
}
|
||||
|
||||
// ValidatingEmitter is an Emitter that can validate against a compiled rule.
|
||||
type ValidatingEmitter interface {
|
||||
Emitter
|
||||
ValidateEmitter(rule *CompiledRule) error
|
||||
}
|
||||
|
||||
// SerialisableEmitter is an Emitter that can be serialised and deserialised to/from JSON.
|
||||
type SerialisableEmitter interface {
|
||||
Emitter
|
||||
@@ -30,6 +36,8 @@ type byGroupsEmitter struct {
|
||||
Emitters
|
||||
}
|
||||
|
||||
var _ ValidatingEmitter = (*byGroupsEmitter)(nil)
|
||||
|
||||
// ByGroups emits a token for each matching group in the rule's regex.
|
||||
func ByGroups(emitters ...Emitter) Emitter {
|
||||
return &byGroupsEmitter{Emitters: emitters}
|
||||
@@ -37,6 +45,13 @@ func ByGroups(emitters ...Emitter) Emitter {
|
||||
|
||||
func (b *byGroupsEmitter) EmitterKind() string { return "bygroups" }
|
||||
|
||||
func (b *byGroupsEmitter) ValidateEmitter(rule *CompiledRule) error {
|
||||
if len(rule.Regexp.GetGroupNumbers())-1 != len(b.Emitters) {
|
||||
return fmt.Errorf("number of groups %d does not match number of emitters %d", len(rule.Regexp.GetGroupNumbers())-1, len(b.Emitters))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *byGroupsEmitter) Emit(groups []string, state *LexerState) Iterator {
|
||||
iterators := make([]Iterator, 0, len(groups)-1)
|
||||
if len(b.Emitters) != len(groups)-1 {
|
||||
|
||||
120
vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go
generated
vendored
120
vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go
generated
vendored
@@ -5,7 +5,9 @@ import (
|
||||
"html"
|
||||
"io"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/alecthomas/chroma/v2"
|
||||
)
|
||||
@@ -32,6 +34,9 @@ func WithCustomCSS(css map[chroma.TokenType]string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithCSSComments adds prefixe comments to the css classes. Defaults to true.
|
||||
func WithCSSComments(b bool) Option { return func(f *Formatter) { f.writeCSSComments = b } }
|
||||
|
||||
// TabWidth sets the number of characters for a tab. Defaults to 8.
|
||||
func TabWidth(width int) Option { return func(f *Formatter) { f.tabWidth = width } }
|
||||
|
||||
@@ -131,7 +136,9 @@ func New(options ...Option) *Formatter {
|
||||
f := &Formatter{
|
||||
baseLineNumber: 1,
|
||||
preWrapper: defaultPreWrapper,
|
||||
writeCSSComments: true,
|
||||
}
|
||||
f.styleCache = newStyleCache(f)
|
||||
for _, option := range options {
|
||||
option(f)
|
||||
}
|
||||
@@ -188,11 +195,13 @@ var (
|
||||
|
||||
// Formatter that generates HTML.
|
||||
type Formatter struct {
|
||||
styleCache *styleCache
|
||||
standalone bool
|
||||
prefix string
|
||||
Classes bool // Exported field to detect when classes are being used
|
||||
allClasses bool
|
||||
customCSS map[chroma.TokenType]string
|
||||
writeCSSComments bool
|
||||
preWrapper PreWrapper
|
||||
inlineCode bool
|
||||
preventSurroundingPre bool
|
||||
@@ -220,12 +229,7 @@ func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Ite
|
||||
//
|
||||
// OTOH we need to be super careful about correct escaping...
|
||||
func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.Token) (err error) { // nolint: gocyclo
|
||||
css := f.styleToCSS(style)
|
||||
if !f.Classes {
|
||||
for t, style := range css {
|
||||
css[t] = compressStyle(style)
|
||||
}
|
||||
}
|
||||
css := f.styleCache.get(style, true)
|
||||
if f.standalone {
|
||||
fmt.Fprint(w, "<html>\n")
|
||||
if f.Classes {
|
||||
@@ -243,7 +247,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
||||
wrapInTable := f.lineNumbers && f.lineNumbersInTable
|
||||
|
||||
lines := chroma.SplitTokensIntoLines(tokens)
|
||||
lineDigits := len(fmt.Sprintf("%d", f.baseLineNumber+len(lines)-1))
|
||||
lineDigits := len(strconv.Itoa(f.baseLineNumber + len(lines) - 1))
|
||||
highlightIndex := 0
|
||||
|
||||
if wrapInTable {
|
||||
@@ -251,7 +255,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
||||
fmt.Fprintf(w, "<div%s>\n", f.styleAttr(css, chroma.PreWrapper))
|
||||
fmt.Fprintf(w, "<table%s><tr>", f.styleAttr(css, chroma.LineTable))
|
||||
fmt.Fprintf(w, "<td%s>\n", f.styleAttr(css, chroma.LineTableTD))
|
||||
fmt.Fprintf(w, f.preWrapper.Start(false, f.styleAttr(css, chroma.PreWrapper)))
|
||||
fmt.Fprintf(w, "%s", f.preWrapper.Start(false, f.styleAttr(css, chroma.PreWrapper)))
|
||||
for index := range lines {
|
||||
line := f.baseLineNumber + index
|
||||
highlight, next := f.shouldHighlight(highlightIndex, line)
|
||||
@@ -273,7 +277,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
||||
fmt.Fprintf(w, "<td%s>\n", f.styleAttr(css, chroma.LineTableTD, "width:100%"))
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, f.preWrapper.Start(true, f.styleAttr(css, chroma.PreWrapper)))
|
||||
fmt.Fprintf(w, "%s", f.preWrapper.Start(true, f.styleAttr(css, chroma.PreWrapper)))
|
||||
|
||||
highlightIndex = 0
|
||||
for index, tokens := range lines {
|
||||
@@ -323,7 +327,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
||||
fmt.Fprint(w, `</span>`) // End of Line
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(w, f.preWrapper.End(true))
|
||||
fmt.Fprintf(w, "%s", f.preWrapper.End(true))
|
||||
|
||||
if wrapInTable {
|
||||
fmt.Fprint(w, "</td></tr></table>\n")
|
||||
@@ -417,21 +421,37 @@ func (f *Formatter) tabWidthStyle() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (f *Formatter) writeCSSRule(w io.Writer, comment string, selector string, styles string) error {
|
||||
if styles == "" {
|
||||
return nil
|
||||
}
|
||||
if f.writeCSSComments && comment != "" {
|
||||
if _, err := fmt.Fprintf(w, "/* %s */ ", comment); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := fmt.Fprintf(w, "%s { %s }\n", selector, styles); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteCSS writes CSS style definitions (without any surrounding HTML).
|
||||
func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error {
|
||||
css := f.styleToCSS(style)
|
||||
css := f.styleCache.get(style, false)
|
||||
|
||||
// Special-case background as it is mapped to the outer ".chroma" class.
|
||||
if _, err := fmt.Fprintf(w, "/* %s */ .%sbg { %s }\n", chroma.Background, f.prefix, css[chroma.Background]); err != nil {
|
||||
if err := f.writeCSSRule(w, chroma.Background.String(), fmt.Sprintf(".%sbg", f.prefix), css[chroma.Background]); err != nil {
|
||||
return err
|
||||
}
|
||||
// Special-case PreWrapper as it is the ".chroma" class.
|
||||
if _, err := fmt.Fprintf(w, "/* %s */ .%schroma { %s }\n", chroma.PreWrapper, f.prefix, css[chroma.PreWrapper]); err != nil {
|
||||
if err := f.writeCSSRule(w, chroma.PreWrapper.String(), fmt.Sprintf(".%schroma", f.prefix), css[chroma.PreWrapper]); err != nil {
|
||||
return err
|
||||
}
|
||||
// Special-case code column of table to expand width.
|
||||
if f.lineNumbers && f.lineNumbersInTable {
|
||||
if _, err := fmt.Fprintf(w, "/* %s */ .%schroma .%s:last-child { width: 100%%; }",
|
||||
chroma.LineTableTD, f.prefix, f.class(chroma.LineTableTD)); err != nil {
|
||||
selector := fmt.Sprintf(".%schroma .%s:last-child", f.prefix, f.class(chroma.LineTableTD))
|
||||
if err := f.writeCSSRule(w, chroma.LineTableTD.String(), selector, "width: 100%;"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -439,7 +459,11 @@ func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error {
|
||||
if f.lineNumbers || f.lineNumbersInTable {
|
||||
targetedLineCSS := StyleEntryToCSS(style.Get(chroma.LineHighlight))
|
||||
for _, tt := range []chroma.TokenType{chroma.LineNumbers, chroma.LineNumbersTable} {
|
||||
fmt.Fprintf(w, "/* %s targeted by URL anchor */ .%schroma .%s:target { %s }\n", tt, f.prefix, f.class(tt), targetedLineCSS)
|
||||
comment := fmt.Sprintf("%s targeted by URL anchor", tt)
|
||||
selector := fmt.Sprintf(".%schroma .%s:target", f.prefix, f.class(tt))
|
||||
if err := f.writeCSSRule(w, comment, selector, targetedLineCSS); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
tts := []int{}
|
||||
@@ -457,8 +481,7 @@ func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error {
|
||||
if class == "" {
|
||||
continue
|
||||
}
|
||||
styles := css[tt]
|
||||
if _, err := fmt.Fprintf(w, "/* %s */ .%schroma .%s { %s }\n", tt, f.prefix, class, styles); err != nil {
|
||||
if err := f.writeCSSRule(w, tt.String(), fmt.Sprintf(".%schroma .%s", f.prefix, class), css[tt]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -505,6 +528,7 @@ func (f *Formatter) styleToCSS(style *chroma.Style) map[chroma.TokenType]string
|
||||
}
|
||||
classes[chroma.Background] += `;` + f.tabWidthStyle()
|
||||
classes[chroma.PreWrapper] += classes[chroma.Background]
|
||||
classes[chroma.PreWrapper] += ` -webkit-text-size-adjust: none;`
|
||||
// Make PreWrapper a grid to show highlight style with full width.
|
||||
if len(f.highlightRanges) > 0 && f.customCSS[chroma.PreWrapper] == `` {
|
||||
classes[chroma.PreWrapper] += `display: grid;`
|
||||
@@ -562,3 +586,63 @@ func compressStyle(s string) string {
|
||||
}
|
||||
return strings.Join(out, ";")
|
||||
}
|
||||
|
||||
const styleCacheLimit = 32
|
||||
|
||||
type styleCacheEntry struct {
|
||||
style *chroma.Style
|
||||
compressed bool
|
||||
cache map[chroma.TokenType]string
|
||||
}
|
||||
|
||||
type styleCache struct {
|
||||
mu sync.Mutex
|
||||
// LRU cache of compiled (and possibly compressed) styles. This is a slice
|
||||
// because the cache size is small, and a slice is sufficiently fast for
|
||||
// small N.
|
||||
cache []styleCacheEntry
|
||||
f *Formatter
|
||||
}
|
||||
|
||||
func newStyleCache(f *Formatter) *styleCache {
|
||||
return &styleCache{f: f}
|
||||
}
|
||||
|
||||
func (l *styleCache) get(style *chroma.Style, compress bool) map[chroma.TokenType]string {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
|
||||
// Look for an existing entry.
|
||||
for i := len(l.cache) - 1; i >= 0; i-- {
|
||||
entry := l.cache[i]
|
||||
if entry.style == style && entry.compressed == compress {
|
||||
// Top of the cache, no need to adjust the order.
|
||||
if i == len(l.cache)-1 {
|
||||
return entry.cache
|
||||
}
|
||||
// Move this entry to the end of the LRU
|
||||
copy(l.cache[i:], l.cache[i+1:])
|
||||
l.cache[len(l.cache)-1] = entry
|
||||
return entry.cache
|
||||
}
|
||||
}
|
||||
|
||||
// No entry, create one.
|
||||
cached := l.f.styleToCSS(style)
|
||||
if !l.f.Classes {
|
||||
for t, style := range cached {
|
||||
cached[t] = compressStyle(style)
|
||||
}
|
||||
}
|
||||
if compress {
|
||||
for t, style := range cached {
|
||||
cached[t] = compressStyle(style)
|
||||
}
|
||||
}
|
||||
// Evict the oldest entry.
|
||||
if len(l.cache) >= styleCacheLimit {
|
||||
l.cache = l.cache[0:copy(l.cache, l.cache[1:])]
|
||||
}
|
||||
l.cache = append(l.cache, styleCacheEntry{style: style, cache: cached, compressed: compress})
|
||||
return cached
|
||||
}
|
||||
|
||||
16
vendor/github.com/alecthomas/chroma/v2/formatters/json.go
generated
vendored
16
vendor/github.com/alecthomas/chroma/v2/formatters/json.go
generated
vendored
@@ -10,11 +10,15 @@ import (
|
||||
|
||||
// JSON formatter outputs the raw token structures as JSON.
|
||||
var JSON = Register("json", chroma.FormatterFunc(func(w io.Writer, s *chroma.Style, it chroma.Iterator) error {
|
||||
fmt.Fprintln(w, "[")
|
||||
if _, err := fmt.Fprintln(w, "["); err != nil {
|
||||
return err
|
||||
}
|
||||
i := 0
|
||||
for t := it(); t != chroma.EOF; t = it() {
|
||||
if i > 0 {
|
||||
fmt.Fprintln(w, ",")
|
||||
if _, err := fmt.Fprintln(w, ","); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
i++
|
||||
bytes, err := json.Marshal(t)
|
||||
@@ -25,7 +29,11 @@ var JSON = Register("json", chroma.FormatterFunc(func(w io.Writer, s *chroma.Sty
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(w)
|
||||
fmt.Fprintln(w, "]")
|
||||
if _, err := fmt.Fprintln(w); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := fmt.Fprintln(w, "]"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}))
|
||||
|
||||
9
vendor/github.com/alecthomas/chroma/v2/formatters/tty_indexed.go
generated
vendored
9
vendor/github.com/alecthomas/chroma/v2/formatters/tty_indexed.go
generated
vendored
@@ -1,7 +1,6 @@
|
||||
package formatters
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
|
||||
@@ -257,13 +256,7 @@ func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style, it chroma
|
||||
}
|
||||
}
|
||||
|
||||
if clr != "" {
|
||||
fmt.Fprint(w, clr)
|
||||
}
|
||||
fmt.Fprint(w, token.Value)
|
||||
if clr != "" {
|
||||
fmt.Fprintf(w, "\033[0m")
|
||||
}
|
||||
writeToken(w, clr, token.Value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
60
vendor/github.com/alecthomas/chroma/v2/formatters/tty_truecolour.go
generated
vendored
60
vendor/github.com/alecthomas/chroma/v2/formatters/tty_truecolour.go
generated
vendored
@@ -3,6 +3,7 @@ package formatters
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
|
||||
"github.com/alecthomas/chroma/v2"
|
||||
)
|
||||
@@ -10,33 +11,66 @@ import (
|
||||
// TTY16m is a true-colour terminal formatter.
|
||||
var TTY16m = Register("terminal16m", chroma.FormatterFunc(trueColourFormatter))
|
||||
|
||||
var crOrCrLf = regexp.MustCompile(`\r?\n`)
|
||||
|
||||
// Print the text with the given formatting, resetting the formatting at the end
|
||||
// of each line and resuming it on the next line.
|
||||
//
|
||||
// This way, a pager (like https://github.com/walles/moar for example) can show
|
||||
// any line in the output by itself, and it will get the right formatting.
|
||||
func writeToken(w io.Writer, formatting string, text string) {
|
||||
if formatting == "" {
|
||||
fmt.Fprint(w, text)
|
||||
return
|
||||
}
|
||||
|
||||
newlineIndices := crOrCrLf.FindAllStringIndex(text, -1)
|
||||
|
||||
afterLastNewline := 0
|
||||
for _, indices := range newlineIndices {
|
||||
newlineStart, afterNewline := indices[0], indices[1]
|
||||
fmt.Fprint(w, formatting)
|
||||
fmt.Fprint(w, text[afterLastNewline:newlineStart])
|
||||
fmt.Fprint(w, "\033[0m")
|
||||
fmt.Fprint(w, text[newlineStart:afterNewline])
|
||||
afterLastNewline = afterNewline
|
||||
}
|
||||
|
||||
if afterLastNewline < len(text) {
|
||||
// Print whatever is left after the last newline
|
||||
fmt.Fprint(w, formatting)
|
||||
fmt.Fprint(w, text[afterLastNewline:])
|
||||
fmt.Fprint(w, "\033[0m")
|
||||
}
|
||||
}
|
||||
|
||||
func trueColourFormatter(w io.Writer, style *chroma.Style, it chroma.Iterator) error {
|
||||
style = clearBackground(style)
|
||||
for token := it(); token != chroma.EOF; token = it() {
|
||||
entry := style.Get(token.Type)
|
||||
if !entry.IsZero() {
|
||||
out := ""
|
||||
if entry.IsZero() {
|
||||
fmt.Fprint(w, token.Value)
|
||||
continue
|
||||
}
|
||||
|
||||
formatting := ""
|
||||
if entry.Bold == chroma.Yes {
|
||||
out += "\033[1m"
|
||||
formatting += "\033[1m"
|
||||
}
|
||||
if entry.Underline == chroma.Yes {
|
||||
out += "\033[4m"
|
||||
formatting += "\033[4m"
|
||||
}
|
||||
if entry.Italic == chroma.Yes {
|
||||
out += "\033[3m"
|
||||
formatting += "\033[3m"
|
||||
}
|
||||
if entry.Colour.IsSet() {
|
||||
out += fmt.Sprintf("\033[38;2;%d;%d;%dm", entry.Colour.Red(), entry.Colour.Green(), entry.Colour.Blue())
|
||||
formatting += fmt.Sprintf("\033[38;2;%d;%d;%dm", entry.Colour.Red(), entry.Colour.Green(), entry.Colour.Blue())
|
||||
}
|
||||
if entry.Background.IsSet() {
|
||||
out += fmt.Sprintf("\033[48;2;%d;%d;%dm", entry.Background.Red(), entry.Background.Green(), entry.Background.Blue())
|
||||
}
|
||||
fmt.Fprint(w, out)
|
||||
}
|
||||
fmt.Fprint(w, token.Value)
|
||||
if !entry.IsZero() {
|
||||
fmt.Fprint(w, "\033[0m")
|
||||
formatting += fmt.Sprintf("\033[48;2;%d;%d;%dm", entry.Background.Red(), entry.Background.Green(), entry.Background.Blue())
|
||||
}
|
||||
|
||||
writeToken(w, formatting, token.Value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
19
vendor/github.com/alecthomas/chroma/v2/iterator.go
generated
vendored
19
vendor/github.com/alecthomas/chroma/v2/iterator.go
generated
vendored
@@ -18,6 +18,17 @@ func (i Iterator) Tokens() []Token {
|
||||
return out
|
||||
}
|
||||
|
||||
// Stdlib converts a Chroma iterator to a Go 1.23-compatible iterator.
|
||||
func (i Iterator) Stdlib() func(yield func(Token) bool) {
|
||||
return func(yield func(Token) bool) {
|
||||
for t := i(); t != EOF; t = i() {
|
||||
if !yield(t) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Concaterator concatenates tokens from a series of iterators.
|
||||
func Concaterator(iterators ...Iterator) Iterator {
|
||||
return func() Token {
|
||||
@@ -47,6 +58,7 @@ func Literator(tokens ...Token) Iterator {
|
||||
// SplitTokensIntoLines splits tokens containing newlines in two.
|
||||
func SplitTokensIntoLines(tokens []Token) (out [][]Token) {
|
||||
var line []Token // nolint: prealloc
|
||||
tokenLoop:
|
||||
for _, token := range tokens {
|
||||
for strings.Contains(token.Value, "\n") {
|
||||
parts := strings.SplitAfterN(token.Value, "\n", 2)
|
||||
@@ -59,6 +71,11 @@ func SplitTokensIntoLines(tokens []Token) (out [][]Token) {
|
||||
line = append(line, clone)
|
||||
out = append(out, line)
|
||||
line = nil
|
||||
|
||||
// If the tail token is empty, don't emit it.
|
||||
if len(token.Value) == 0 {
|
||||
continue tokenLoop
|
||||
}
|
||||
}
|
||||
line = append(line, token)
|
||||
}
|
||||
@@ -72,5 +89,5 @@ func SplitTokensIntoLines(tokens []Token) (out [][]Token) {
|
||||
out = out[:len(out)-1]
|
||||
}
|
||||
}
|
||||
return
|
||||
return out
|
||||
}
|
||||
|
||||
17
vendor/github.com/alecthomas/chroma/v2/lexer.go
generated
vendored
17
vendor/github.com/alecthomas/chroma/v2/lexer.go
generated
vendored
@@ -130,6 +130,23 @@ type Lexer interface {
|
||||
AnalyseText(text string) float32
|
||||
}
|
||||
|
||||
// Trace is the trace of a tokenisation process.
|
||||
type Trace struct {
|
||||
Lexer string `json:"lexer"`
|
||||
State string `json:"state"`
|
||||
Rule int `json:"rule"`
|
||||
Pattern string `json:"pattern"`
|
||||
Pos int `json:"pos"`
|
||||
Length int `json:"length"`
|
||||
Elapsed float64 `json:"elapsedMs"` // Elapsed time spent matching for this rule.
|
||||
}
|
||||
|
||||
// TracingLexer is a Lexer that can trace its tokenisation process.
|
||||
type TracingLexer interface {
|
||||
Lexer
|
||||
SetTracing(enable bool)
|
||||
}
|
||||
|
||||
// Lexers is a slice of lexers sortable by name.
|
||||
type Lexers []Lexer
|
||||
|
||||
|
||||
180
vendor/github.com/alecthomas/chroma/v2/lexers/caddyfile.go
generated
vendored
180
vendor/github.com/alecthomas/chroma/v2/lexers/caddyfile.go
generated
vendored
@@ -4,52 +4,82 @@ import (
|
||||
. "github.com/alecthomas/chroma/v2" // nolint
|
||||
)
|
||||
|
||||
// Matcher token stub for docs, or
|
||||
// Named matcher: @name, or
|
||||
// Path matcher: /foo, or
|
||||
// Wildcard path matcher: *
|
||||
// nolint: gosec
|
||||
var caddyfileMatcherTokenRegexp = `(\[\<matcher\>\]|@[^\s]+|/[^\s]+|\*)`
|
||||
|
||||
// Comment at start of line, or
|
||||
// Comment preceded by whitespace
|
||||
var caddyfileCommentRegexp = `(^|\s+)#.*\n`
|
||||
|
||||
// caddyfileCommon are the rules common to both of the lexer variants
|
||||
func caddyfileCommonRules() Rules {
|
||||
return Rules{
|
||||
"site_block_common": {
|
||||
Include("site_body"),
|
||||
// Any other directive
|
||||
{`[^\s#]+`, Keyword, Push("directive")},
|
||||
Include("base"),
|
||||
},
|
||||
"site_body": {
|
||||
// Import keyword
|
||||
{`(import)(\s+)([^\s]+)`, ByGroups(Keyword, Text, NameVariableMagic), nil},
|
||||
{`\b(import|invoke)\b( [^\s#]+)`, ByGroups(Keyword, Text), Push("subdirective")},
|
||||
// Matcher definition
|
||||
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
|
||||
// Matcher token stub for docs
|
||||
{`\[\<matcher\>\]`, NameDecorator, Push("matcher")},
|
||||
// These cannot have matchers but may have things that look like
|
||||
// matchers in their arguments, so we just parse as a subdirective.
|
||||
{`try_files`, Keyword, Push("subdirective")},
|
||||
{`\b(try_files|tls|log|bind)\b`, Keyword, Push("subdirective")},
|
||||
// These are special, they can nest more directives
|
||||
{`handle_errors|handle|route|handle_path|not`, Keyword, Push("nested_directive")},
|
||||
// Any other directive
|
||||
{`[^\s#]+`, Keyword, Push("directive")},
|
||||
Include("base"),
|
||||
{`\b(handle_errors|handle_path|handle_response|replace_status|handle|route)\b`, Keyword, Push("nested_directive")},
|
||||
// uri directive has special syntax
|
||||
{`\b(uri)\b`, Keyword, Push("uri_directive")},
|
||||
},
|
||||
"matcher": {
|
||||
{`\{`, Punctuation, Push("block")},
|
||||
// Not can be one-liner
|
||||
{`not`, Keyword, Push("deep_not_matcher")},
|
||||
// Heredoc for CEL expression
|
||||
Include("heredoc"),
|
||||
// Backtick for CEL expression
|
||||
{"`", StringBacktick, Push("backticks")},
|
||||
// Any other same-line matcher
|
||||
{`[^\s#]+`, Keyword, Push("arguments")},
|
||||
// Terminators
|
||||
{`\n`, Text, Pop(1)},
|
||||
{`\s*\n`, Text, Pop(1)},
|
||||
{`\}`, Punctuation, Pop(1)},
|
||||
Include("base"),
|
||||
},
|
||||
"block": {
|
||||
{`\}`, Punctuation, Pop(2)},
|
||||
// Using double quotes doesn't stop at spaces
|
||||
{`"`, StringDouble, Push("double_quotes")},
|
||||
// Using backticks doesn't stop at spaces
|
||||
{"`", StringBacktick, Push("backticks")},
|
||||
// Not can be one-liner
|
||||
{`not`, Keyword, Push("not_matcher")},
|
||||
// Any other subdirective
|
||||
// Directives & matcher definitions
|
||||
Include("site_body"),
|
||||
// Any directive
|
||||
{`[^\s#]+`, Keyword, Push("subdirective")},
|
||||
Include("base"),
|
||||
},
|
||||
"nested_block": {
|
||||
{`\}`, Punctuation, Pop(2)},
|
||||
// Matcher definition
|
||||
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
|
||||
// Something that starts with literally < is probably a docs stub
|
||||
{`\<[^#]+\>`, Keyword, Push("nested_directive")},
|
||||
// Any other directive
|
||||
{`[^\s#]+`, Keyword, Push("nested_directive")},
|
||||
// Using double quotes doesn't stop at spaces
|
||||
{`"`, StringDouble, Push("double_quotes")},
|
||||
// Using backticks doesn't stop at spaces
|
||||
{"`", StringBacktick, Push("backticks")},
|
||||
// Not can be one-liner
|
||||
{`not`, Keyword, Push("not_matcher")},
|
||||
// Directives & matcher definitions
|
||||
Include("site_body"),
|
||||
// Any other subdirective
|
||||
{`[^\s#]+`, Keyword, Push("directive")},
|
||||
Include("base"),
|
||||
},
|
||||
"not_matcher": {
|
||||
@@ -66,69 +96,97 @@ func caddyfileCommonRules() Rules {
|
||||
},
|
||||
"directive": {
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
Include("matcher_token"),
|
||||
Include("comments_pop_1"),
|
||||
{`\n`, Text, Pop(1)},
|
||||
{caddyfileMatcherTokenRegexp, NameDecorator, Push("arguments")},
|
||||
{caddyfileCommentRegexp, CommentSingle, Pop(1)},
|
||||
{`\s*\n`, Text, Pop(1)},
|
||||
Include("base"),
|
||||
},
|
||||
"nested_directive": {
|
||||
{`\{(?=\s)`, Punctuation, Push("nested_block")},
|
||||
Include("matcher_token"),
|
||||
Include("comments_pop_1"),
|
||||
{`\n`, Text, Pop(1)},
|
||||
{caddyfileMatcherTokenRegexp, NameDecorator, Push("nested_arguments")},
|
||||
{caddyfileCommentRegexp, CommentSingle, Pop(1)},
|
||||
{`\s*\n`, Text, Pop(1)},
|
||||
Include("base"),
|
||||
},
|
||||
"subdirective": {
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
Include("comments_pop_1"),
|
||||
{`\n`, Text, Pop(1)},
|
||||
{caddyfileCommentRegexp, CommentSingle, Pop(1)},
|
||||
{`\s*\n`, Text, Pop(1)},
|
||||
Include("base"),
|
||||
},
|
||||
"arguments": {
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
Include("comments_pop_2"),
|
||||
{caddyfileCommentRegexp, CommentSingle, Pop(2)},
|
||||
{`\\\n`, Text, nil}, // Skip escaped newlines
|
||||
{`\n`, Text, Pop(2)},
|
||||
{`\s*\n`, Text, Pop(2)},
|
||||
Include("base"),
|
||||
},
|
||||
"nested_arguments": {
|
||||
{`\{(?=\s)`, Punctuation, Push("nested_block")},
|
||||
{caddyfileCommentRegexp, CommentSingle, Pop(2)},
|
||||
{`\\\n`, Text, nil}, // Skip escaped newlines
|
||||
{`\s*\n`, Text, Pop(2)},
|
||||
Include("base"),
|
||||
},
|
||||
"deep_subdirective": {
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
Include("comments_pop_3"),
|
||||
{`\n`, Text, Pop(3)},
|
||||
{caddyfileCommentRegexp, CommentSingle, Pop(3)},
|
||||
{`\s*\n`, Text, Pop(3)},
|
||||
Include("base"),
|
||||
},
|
||||
"matcher_token": {
|
||||
{`@[^\s]+`, NameDecorator, Push("arguments")}, // Named matcher
|
||||
{`/[^\s]+`, NameDecorator, Push("arguments")}, // Path matcher
|
||||
{`\*`, NameDecorator, Push("arguments")}, // Wildcard path matcher
|
||||
{`\[\<matcher\>\]`, NameDecorator, Push("arguments")}, // Matcher token stub for docs
|
||||
"uri_directive": {
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
{caddyfileMatcherTokenRegexp, NameDecorator, nil},
|
||||
{`(strip_prefix|strip_suffix|replace|path_regexp)`, NameConstant, Push("arguments")},
|
||||
{caddyfileCommentRegexp, CommentSingle, Pop(1)},
|
||||
{`\s*\n`, Text, Pop(1)},
|
||||
Include("base"),
|
||||
},
|
||||
"comments": {
|
||||
{`^#.*\n`, CommentSingle, nil}, // Comment at start of line
|
||||
{`\s+#.*\n`, CommentSingle, nil}, // Comment preceded by whitespace
|
||||
"double_quotes": {
|
||||
Include("placeholder"),
|
||||
{`\\"`, StringDouble, nil},
|
||||
{`[^"]`, StringDouble, nil},
|
||||
{`"`, StringDouble, Pop(1)},
|
||||
},
|
||||
"comments_pop_1": {
|
||||
{`^#.*\n`, CommentSingle, Pop(1)}, // Comment at start of line
|
||||
{`\s+#.*\n`, CommentSingle, Pop(1)}, // Comment preceded by whitespace
|
||||
"backticks": {
|
||||
Include("placeholder"),
|
||||
{"\\\\`", StringBacktick, nil},
|
||||
{"[^`]", StringBacktick, nil},
|
||||
{"`", StringBacktick, Pop(1)},
|
||||
},
|
||||
"comments_pop_2": {
|
||||
{`^#.*\n`, CommentSingle, Pop(2)}, // Comment at start of line
|
||||
{`\s+#.*\n`, CommentSingle, Pop(2)}, // Comment preceded by whitespace
|
||||
"optional": {
|
||||
// Docs syntax for showing optional parts with [ ]
|
||||
{`\[`, Punctuation, Push("optional")},
|
||||
Include("name_constants"),
|
||||
{`\|`, Punctuation, nil},
|
||||
{`[^\[\]\|]+`, String, nil},
|
||||
{`\]`, Punctuation, Pop(1)},
|
||||
},
|
||||
"comments_pop_3": {
|
||||
{`^#.*\n`, CommentSingle, Pop(3)}, // Comment at start of line
|
||||
{`\s+#.*\n`, CommentSingle, Pop(3)}, // Comment preceded by whitespace
|
||||
"heredoc": {
|
||||
{`(<<([a-zA-Z0-9_-]+))(\n(.*|\n)*)(\s*)(\2)`, ByGroups(StringHeredoc, nil, String, String, String, StringHeredoc), nil},
|
||||
},
|
||||
"name_constants": {
|
||||
{`\b(most_recently_modified|largest_size|smallest_size|first_exist|internal|disable_redirects|ignore_loaded_certs|disable_certs|private_ranges|first|last|before|after|on|off)\b(\||(?=\]|\s|$))`, ByGroups(NameConstant, Punctuation), nil},
|
||||
},
|
||||
"placeholder": {
|
||||
// Placeholder with dots, colon for default value, brackets for args[0:]
|
||||
{`\{[\w+.\[\]\:\$-]+\}`, StringEscape, nil},
|
||||
// Handle opening brackets with no matching closing one
|
||||
{`\{[^\}\s]*\b`, String, nil},
|
||||
},
|
||||
"base": {
|
||||
Include("comments"),
|
||||
{`(on|off|first|last|before|after|internal|strip_prefix|strip_suffix|replace)\b`, NameConstant, nil},
|
||||
{`(https?://)?([a-z0-9.-]+)(:)([0-9]+)`, ByGroups(Name, Name, Punctuation, LiteralNumberInteger), nil},
|
||||
{`[a-z-]+/[a-z-+]+`, LiteralString, nil},
|
||||
{`[0-9]+[km]?\b`, LiteralNumberInteger, nil},
|
||||
{`\{[\w+.\$-]+\}`, LiteralStringEscape, nil}, // Placeholder
|
||||
{`\[(?=[^#{}$]+\])`, Punctuation, nil},
|
||||
{`\]|\|`, Punctuation, nil},
|
||||
{`[^\s#{}$\]]+`, LiteralString, nil},
|
||||
{caddyfileCommentRegexp, CommentSingle, nil},
|
||||
{`\[\<matcher\>\]`, NameDecorator, nil},
|
||||
Include("name_constants"),
|
||||
Include("heredoc"),
|
||||
{`(https?://)?([a-z0-9.-]+)(:)([0-9]+)([^\s]*)`, ByGroups(Name, Name, Punctuation, NumberInteger, Name), nil},
|
||||
{`\[`, Punctuation, Push("optional")},
|
||||
{"`", StringBacktick, Push("backticks")},
|
||||
{`"`, StringDouble, Push("double_quotes")},
|
||||
Include("placeholder"),
|
||||
{`[a-z-]+/[a-z-+]+`, String, nil},
|
||||
{`[0-9]+([smhdk]|ns|us|µs|ms)?\b`, NumberInteger, nil},
|
||||
{`[^\s\n#\{]+`, String, nil},
|
||||
{`/[^\s#]*`, Name, nil},
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
@@ -149,27 +207,29 @@ var Caddyfile = Register(MustNewLexer(
|
||||
func caddyfileRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("comments"),
|
||||
{caddyfileCommentRegexp, CommentSingle, nil},
|
||||
// Global options block
|
||||
{`^\s*(\{)\s*$`, ByGroups(Punctuation), Push("globals")},
|
||||
// Top level import
|
||||
{`(import)(\s+)([^\s]+)`, ByGroups(Keyword, Text, NameVariableMagic), nil},
|
||||
// Snippets
|
||||
{`(\([^\s#]+\))(\s*)(\{)`, ByGroups(NameVariableAnonymous, Text, Punctuation), Push("snippet")},
|
||||
{`(&?\([^\s#]+\))(\s*)(\{)`, ByGroups(NameVariableAnonymous, Text, Punctuation), Push("snippet")},
|
||||
// Site label
|
||||
{`[^#{(\s,]+`, GenericHeading, Push("label")},
|
||||
// Site label with placeholder
|
||||
{`\{[\w+.\$-]+\}`, LiteralStringEscape, Push("label")},
|
||||
{`\{[\w+.\[\]\:\$-]+\}`, StringEscape, Push("label")},
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
"globals": {
|
||||
{`\}`, Punctuation, Pop(1)},
|
||||
{`[^\s#]+`, Keyword, Push("directive")},
|
||||
// Global options are parsed as subdirectives (no matcher)
|
||||
{`[^\s#]+`, Keyword, Push("subdirective")},
|
||||
Include("base"),
|
||||
},
|
||||
"snippet": {
|
||||
{`\}`, Punctuation, Pop(1)},
|
||||
// Matcher definition
|
||||
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
|
||||
// Any directive
|
||||
Include("site_body"),
|
||||
// Any other directive
|
||||
{`[^\s#]+`, Keyword, Push("directive")},
|
||||
Include("base"),
|
||||
},
|
||||
@@ -179,7 +239,7 @@ func caddyfileRules() Rules {
|
||||
{`,\s*\n?`, Text, nil},
|
||||
{` `, Text, nil},
|
||||
// Site label with placeholder
|
||||
{`\{[\w+.\$-]+\}`, LiteralStringEscape, nil},
|
||||
Include("placeholder"),
|
||||
// Site label
|
||||
{`[^#{(\s,]+`, GenericHeading, nil},
|
||||
// Comment after non-block label (hack because comments end in \n)
|
||||
|
||||
3
vendor/github.com/alecthomas/chroma/v2/lexers/embedded/angular2.xml
generated
vendored
3
vendor/github.com/alecthomas/chroma/v2/lexers/embedded/angular2.xml
generated
vendored
@@ -45,7 +45,7 @@
|
||||
<token type="Punctuation" />
|
||||
<token type="NameAttribute" />
|
||||
<token type="Punctuation" />
|
||||
<token type="Text"/>
|
||||
<token type="TextWhitespace" />
|
||||
</bygroups>
|
||||
</rule>
|
||||
<rule pattern="([*#])([\w:.-]+)(\s*)(=)(\s*)">
|
||||
@@ -54,6 +54,7 @@
|
||||
<token type="NameAttribute" />
|
||||
<token type="Punctuation" />
|
||||
<token type="Operator" />
|
||||
<token type="TextWhitespace" />
|
||||
</bygroups>
|
||||
<push state="attr" />
|
||||
</rule>
|
||||
|
||||
51
vendor/github.com/alecthomas/chroma/v2/lexers/embedded/applescript.xml
generated
vendored
51
vendor/github.com/alecthomas/chroma/v2/lexers/embedded/applescript.xml
generated
vendored
@@ -33,7 +33,9 @@
|
||||
<token type="Text" />
|
||||
</bygroups>
|
||||
</rule>
|
||||
<rule pattern="\b((?:considering|ignoring)\s*)(application responses|case|diacriticals|hyphens|numeric strings|punctuation|white space)">
|
||||
<rule
|
||||
pattern="\b((?:considering|ignoring)\s*)(application responses|case|diacriticals|hyphens|numeric strings|punctuation|white space)"
|
||||
>
|
||||
<bygroups>
|
||||
<token type="Keyword" />
|
||||
<token type="NameBuiltin" />
|
||||
@@ -42,14 +44,15 @@
|
||||
<rule pattern="(-|\*|\+|&|≠|>=?|<=?|=|≥|≤|/|÷|\^)">
|
||||
<token type="Operator" />
|
||||
</rule>
|
||||
<rule pattern="\b(and|or|is equal|equals|(is )?equal to|is not|isn't|isn't equal( to)?|is not equal( to)?|doesn't equal|does not equal|(is )?greater than|comes after|is not less than or equal( to)?|isn't less than or equal( to)?|(is )?less than|comes before|is not greater than or equal( to)?|isn't greater than or equal( to)?|(is )?greater than or equal( to)?|is not less than|isn't less than|does not come before|doesn't come before|(is )?less than or equal( to)?|is not greater than|isn't greater than|does not come after|doesn't come after|starts? with|begins? with|ends? with|contains?|does not contain|doesn't contain|is in|is contained by|is not in|is not contained by|isn't contained by|div|mod|not|(a )?(ref( to)?|reference to)|is|does)\b">
|
||||
<rule
|
||||
pattern="\b(and|or|is equal|equals|(is )?equal to|is not|isn't|isn't equal( to)?|is not equal( to)?|doesn't equal|does not equal|(is )?greater than|comes after|is not less than or equal( to)?|isn't less than or equal( to)?|(is )?less than|comes before|is not greater than or equal( to)?|isn't greater than or equal( to)?|(is )?greater than or equal( to)?|is not less than|isn't less than|does not come before|doesn't come before|(is )?less than or equal( to)?|is not greater than|isn't greater than|does not come after|doesn't come after|starts? with|begins? with|ends? with|contains?|does not contain|doesn't contain|is in|is contained by|is not in|is not contained by|isn't contained by|div|mod|not|(a )?(ref( to)?|reference to)|is|does)\b"
|
||||
>
|
||||
<token type="OperatorWord" />
|
||||
</rule>
|
||||
<rule pattern="^(\s*(?:on|end)\s+)(zoomed|write to file|will zoom|will show|will select tab view item|will resize( sub views)?|will resign active|will quit|will pop up|will open|will move|will miniaturize|will hide|will finish launching|will display outline cell|will display item cell|will display cell|will display browser cell|will dismiss|will close|will become active|was miniaturized|was hidden|update toolbar item|update parameters|update menu item|shown|should zoom|should selection change|should select tab view item|should select row|should select item|should select column|should quit( after last window closed)?|should open( untitled)?|should expand item|should end editing|should collapse item|should close|should begin editing|selection changing|selection changed|selected tab view item|scroll wheel|rows changed|right mouse up|right mouse dragged|right mouse down|resized( sub views)?|resigned main|resigned key|resigned active|read from file|prepare table drop|prepare table drag|prepare outline drop|prepare outline drag|prepare drop|plugin loaded|parameters updated|panel ended|opened|open untitled|number of rows|number of items|number of browser rows|moved|mouse up|mouse moved|mouse exited|mouse entered|mouse dragged|mouse down|miniaturized|load data representation|launched|keyboard up|keyboard down|items changed|item value changed|item value|item expandable|idle|exposed|end editing|drop|drag( (entered|exited|updated))?|double clicked|document nib name|dialog ended|deminiaturized|data representation|conclude drop|column resized|column moved|column clicked|closed|clicked toolbar item|clicked|choose menu item|child of item|changed|change item value|change cell value|cell value changed|cell value|bounds changed|begin editing|became main|became key|awake from nib|alert ended|activated|action|accept table drop|accept outline drop)">
|
||||
<bygroups>
|
||||
<rule
|
||||
pattern="^(\s*(?:on|end)\s+)(zoomed|write to file|will zoom|will show|will select tab view item|will resize( sub views)?|will resign active|will quit|will pop up|will open|will move|will miniaturize|will hide|will finish launching|will display outline cell|will display item cell|will display cell|will display browser cell|will dismiss|will close|will become active|was miniaturized|was hidden|update toolbar item|update parameters|update menu item|shown|should zoom|should selection change|should select tab view item|should select row|should select item|should select column|should quit( after last window closed)?|should open( untitled)?|should expand item|should end editing|should collapse item|should close|should begin editing|selection changing|selection changed|selected tab view item|scroll wheel|rows changed|right mouse up|right mouse dragged|right mouse down|resized( sub views)?|resigned main|resigned key|resigned active|read from file|prepare table drop|prepare table drag|prepare outline drop|prepare outline drag|prepare drop|plugin loaded|parameters updated|panel ended|opened|open untitled|number of rows|number of items|number of browser rows|moved|mouse up|mouse moved|mouse exited|mouse entered|mouse dragged|mouse down|miniaturized|load data representation|launched|keyboard up|keyboard down|items changed|item value changed|item value|item expandable|idle|exposed|end editing|drop|drag( (entered|exited|updated))?|double clicked|document nib name|dialog ended|deminiaturized|data representation|conclude drop|column resized|column moved|column clicked|closed|clicked toolbar item|clicked|choose menu item|child of item|changed|change item value|change cell value|cell value changed|cell value|bounds changed|begin editing|became main|became key|awake from nib|alert ended|activated|action|accept table drop|accept outline drop)"
|
||||
>
|
||||
<token type="Keyword" />
|
||||
<token type="NameFunction"/>
|
||||
</bygroups>
|
||||
</rule>
|
||||
<rule pattern="^(\s*)(in|on|script|to)(\s+)">
|
||||
<bygroups>
|
||||
@@ -58,19 +61,27 @@
|
||||
<token type="Text" />
|
||||
</bygroups>
|
||||
</rule>
|
||||
<rule pattern="\b(as )(alias |application |boolean |class |constant |date |file |integer |list |number |POSIX file |real |record |reference |RGB color |script |text |unit types|(?:Unicode )?text|string)\b">
|
||||
<rule
|
||||
pattern="\b(as )(alias |application |boolean |class |constant |date |file |integer |list |number |POSIX file |real |record |reference |RGB color |script |text |unit types|(?:Unicode )?text|string)\b"
|
||||
>
|
||||
<bygroups>
|
||||
<token type="Keyword" />
|
||||
<token type="NameClass" />
|
||||
</bygroups>
|
||||
</rule>
|
||||
<rule pattern="\b(AppleScript|current application|false|linefeed|missing value|pi|quote|result|return|space|tab|text item delimiters|true|version)\b">
|
||||
<rule
|
||||
pattern="\b(AppleScript|current application|false|linefeed|missing value|pi|quote|result|return|space|tab|text item delimiters|true|version)\b"
|
||||
>
|
||||
<token type="NameConstant" />
|
||||
</rule>
|
||||
<rule pattern="\b(ASCII (character|number)|activate|beep|choose URL|choose application|choose color|choose file( name)?|choose folder|choose from list|choose remote application|clipboard info|close( access)?|copy|count|current date|delay|delete|display (alert|dialog)|do shell script|duplicate|exists|get eof|get volume settings|info for|launch|list (disks|folder)|load script|log|make|mount volume|new|offset|open( (for access|location))?|path to|print|quit|random number|read|round|run( script)?|say|scripting components|set (eof|the clipboard to|volume)|store script|summarize|system attribute|system info|the clipboard|time to GMT|write|quoted form)\b">
|
||||
<rule
|
||||
pattern="\b(ASCII (character|number)|activate|beep|choose URL|choose application|choose color|choose file( name)?|choose folder|choose from list|choose remote application|clipboard info|close( access)?|copy|count|current date|delay|delete|display (alert|dialog)|do shell script|duplicate|exists|get eof|get volume settings|info for|launch|list (disks|folder)|load script|log|make|mount volume|new|offset|open( (for access|location))?|path to|print|quit|random number|read|round|run( script)?|say|scripting components|set (eof|the clipboard to|volume)|store script|summarize|system attribute|system info|the clipboard|time to GMT|write|quoted form)\b"
|
||||
>
|
||||
<token type="NameBuiltin" />
|
||||
</rule>
|
||||
<rule pattern="\b(considering|else|error|exit|from|if|ignoring|in|repeat|tell|then|times|to|try|until|using terms from|while|with|with timeout( of)?|with transaction|by|continue|end|its?|me|my|return|of|as)\b">
|
||||
<rule
|
||||
pattern="\b(considering|else|error|exit|from|if|ignoring|in|repeat|tell|then|times|to|try|until|using terms from|while|with|with timeout( of)?|with transaction|by|continue|end|its?|me|my|return|of|as)\b"
|
||||
>
|
||||
<token type="Keyword" />
|
||||
</rule>
|
||||
<rule pattern="\b(global|local|prop(erty)?|set|get)\b">
|
||||
@@ -82,19 +93,29 @@
|
||||
<rule pattern="\b(attachment|attribute run|character|day|month|paragraph|word|year)s?\b">
|
||||
<token type="NameBuiltin" />
|
||||
</rule>
|
||||
<rule pattern="\b(about|above|against|apart from|around|aside from|at|below|beneath|beside|between|for|given|instead of|on|onto|out of|over|since)\b">
|
||||
<rule
|
||||
pattern="\b(about|above|against|apart from|around|aside from|at|below|beneath|beside|between|for|given|instead of|on|onto|out of|over|since)\b"
|
||||
>
|
||||
<token type="NameBuiltin" />
|
||||
</rule>
|
||||
<rule pattern="\b(accepts arrow key|action method|active|alignment|allowed identifiers|allows branch selection|allows column reordering|allows column resizing|allows column selection|allows customization|allows editing text attributes|allows empty selection|allows mixed state|allows multiple selection|allows reordering|allows undo|alpha( value)?|alternate image|alternate increment value|alternate title|animation delay|associated file name|associated object|auto completes|auto display|auto enables items|auto repeat|auto resizes( outline column)?|auto save expanded items|auto save name|auto save table columns|auto saves configuration|auto scroll|auto sizes all columns to fit|auto sizes cells|background color|bezel state|bezel style|bezeled|border rect|border type|bordered|bounds( rotation)?|box type|button returned|button type|can choose directories|can choose files|can draw|can hide|cell( (background color|size|type))?|characters|class|click count|clicked( data)? column|clicked data item|clicked( data)? row|closeable|collating|color( (mode|panel))|command key down|configuration|content(s| (size|view( margins)?))?|context|continuous|control key down|control size|control tint|control view|controller visible|coordinate system|copies( on scroll)?|corner view|current cell|current column|current( field)? editor|current( menu)? item|current row|current tab view item|data source|default identifiers|delta (x|y|z)|destination window|directory|display mode|displayed cell|document( (edited|rect|view))?|double value|dragged column|dragged distance|dragged items|draws( cell)? background|draws grid|dynamically scrolls|echos bullets|edge|editable|edited( data)? column|edited data item|edited( data)? row|enabled|enclosing scroll view|ending page|error handling|event number|event type|excluded from windows menu|executable path|expanded|fax number|field editor|file kind|file name|file type|first responder|first visible column|flipped|floating|font( panel)?|formatter|frameworks path|frontmost|gave up|grid color|has data items|has horizontal ruler|has horizontal scroller|has parent data item|has resize indicator|has shadow|has sub menu|has vertical ruler|has vertical scroller|header cell|header view|hidden|hides when deactivated|highlights by|horizontal line scroll|horizontal page scroll|horizontal ruler view|horizontally resizable|icon image|id|identifier|ignores multiple clicks|image( (alignment|dims when disabled|frame style|scaling))?|imports graphics|increment value|indentation per level|indeterminate|index|integer value|intercell spacing|item height|key( (code|equivalent( modifier)?|window))?|knob thickness|label|last( visible)? column|leading offset|leaf|level|line scroll|loaded|localized sort|location|loop mode|main( (bunde|menu|window))?|marker follows cell|matrix mode|maximum( content)? size|maximum visible columns|menu( form representation)?|miniaturizable|miniaturized|minimized image|minimized title|minimum column width|minimum( content)? size|modal|modified|mouse down state|movie( (controller|file|rect))?|muted|name|needs display|next state|next text|number of tick marks|only tick mark values|opaque|open panel|option key down|outline table column|page scroll|pages across|pages down|palette label|pane splitter|parent data item|parent window|pasteboard|path( (names|separator))?|playing|plays every frame|plays selection only|position|preferred edge|preferred type|pressure|previous text|prompt|properties|prototype cell|pulls down|rate|released when closed|repeated|requested print time|required file type|resizable|resized column|resource path|returns records|reuses columns|rich text|roll over|row height|rulers visible|save panel|scripts path|scrollable|selectable( identifiers)?|selected cell|selected( data)? columns?|selected data items?|selected( data)? rows?|selected item identifier|selection by rect|send action on arrow key|sends action when done editing|separates columns|separator item|sequence number|services menu|shared frameworks path|shared support path|sheet|shift key down|shows alpha|shows state by|size( mode)?|smart insert delete enabled|sort case sensitivity|sort column|sort order|sort type|sorted( data rows)?|sound|source( mask)?|spell checking enabled|starting page|state|string value|sub menu|super menu|super view|tab key traverses cells|tab state|tab type|tab view|table view|tag|target( printer)?|text color|text container insert|text container origin|text returned|tick mark position|time stamp|title(d| (cell|font|height|position|rect))?|tool tip|toolbar|trailing offset|transparent|treat packages as directories|truncated labels|types|unmodified characters|update views|use sort indicator|user defaults|uses data source|uses ruler|uses threaded animation|uses title from previous column|value wraps|version|vertical( (line scroll|page scroll|ruler view))?|vertically resizable|view|visible( document rect)?|volume|width|window|windows menu|wraps|zoomable|zoomed)\b">
|
||||
<rule
|
||||
pattern="\b(accepts arrow key|action method|active|alignment|allowed identifiers|allows branch selection|allows column reordering|allows column resizing|allows column selection|allows customization|allows editing text attributes|allows empty selection|allows mixed state|allows multiple selection|allows reordering|allows undo|alpha( value)?|alternate image|alternate increment value|alternate title|animation delay|associated file name|associated object|auto completes|auto display|auto enables items|auto repeat|auto resizes( outline column)?|auto save expanded items|auto save name|auto save table columns|auto saves configuration|auto scroll|auto sizes all columns to fit|auto sizes cells|background color|bezel state|bezel style|bezeled|border rect|border type|bordered|bounds( rotation)?|box type|button returned|button type|can choose directories|can choose files|can draw|can hide|cell( (background color|size|type))?|characters|class|click count|clicked( data)? column|clicked data item|clicked( data)? row|closeable|collating|color( (mode|panel))|command key down|configuration|content(s| (size|view( margins)?))?|context|continuous|control key down|control size|control tint|control view|controller visible|coordinate system|copies( on scroll)?|corner view|current cell|current column|current( field)? editor|current( menu)? item|current row|current tab view item|data source|default identifiers|delta (x|y|z)|destination window|directory|display mode|displayed cell|document( (edited|rect|view))?|double value|dragged column|dragged distance|dragged items|draws( cell)? background|draws grid|dynamically scrolls|echos bullets|edge|editable|edited( data)? column|edited data item|edited( data)? row|enabled|enclosing scroll view|ending page|error handling|event number|event type|excluded from windows menu|executable path|expanded|fax number|field editor|file kind|file name|file type|first responder|first visible column|flipped|floating|font( panel)?|formatter|frameworks path|frontmost|gave up|grid color|has data items|has horizontal ruler|has horizontal scroller|has parent data item|has resize indicator|has shadow|has sub menu|has vertical ruler|has vertical scroller|header cell|header view|hidden|hides when deactivated|highlights by|horizontal line scroll|horizontal page scroll|horizontal ruler view|horizontally resizable|icon image|id|identifier|ignores multiple clicks|image( (alignment|dims when disabled|frame style|scaling))?|imports graphics|increment value|indentation per level|indeterminate|index|integer value|intercell spacing|item height|key( (code|equivalent( modifier)?|window))?|knob thickness|label|last( visible)? column|leading offset|leaf|level|line scroll|loaded|localized sort|location|loop mode|main( (bunde|menu|window))?|marker follows cell|matrix mode|maximum( content)? size|maximum visible columns|menu( form representation)?|miniaturizable|miniaturized|minimized image|minimized title|minimum column width|minimum( content)? size|modal|modified|mouse down state|movie( (controller|file|rect))?|muted|name|needs display|next state|next text|number of tick marks|only tick mark values|opaque|open panel|option key down|outline table column|page scroll|pages across|pages down|palette label|pane splitter|parent data item|parent window|pasteboard|path( (names|separator))?|playing|plays every frame|plays selection only|position|preferred edge|preferred type|pressure|previous text|prompt|properties|prototype cell|pulls down|rate|released when closed|repeated|requested print time|required file type|resizable|resized column|resource path|returns records|reuses columns|rich text|roll over|row height|rulers visible|save panel|scripts path|scrollable|selectable( identifiers)?|selected cell|selected( data)? columns?|selected data items?|selected( data)? rows?|selected item identifier|selection by rect|send action on arrow key|sends action when done editing|separates columns|separator item|sequence number|services menu|shared frameworks path|shared support path|sheet|shift key down|shows alpha|shows state by|size( mode)?|smart insert delete enabled|sort case sensitivity|sort column|sort order|sort type|sorted( data rows)?|sound|source( mask)?|spell checking enabled|starting page|state|string value|sub menu|super menu|super view|tab key traverses cells|tab state|tab type|tab view|table view|tag|target( printer)?|text color|text container insert|text container origin|text returned|tick mark position|time stamp|title(d| (cell|font|height|position|rect))?|tool tip|toolbar|trailing offset|transparent|treat packages as directories|truncated labels|types|unmodified characters|update views|use sort indicator|user defaults|uses data source|uses ruler|uses threaded animation|uses title from previous column|value wraps|version|vertical( (line scroll|page scroll|ruler view))?|vertically resizable|view|visible( document rect)?|volume|width|window|windows menu|wraps|zoomable|zoomed)\b"
|
||||
>
|
||||
<token type="NameAttribute" />
|
||||
</rule>
|
||||
<rule pattern="\b(action cell|alert reply|application|box|browser( cell)?|bundle|button( cell)?|cell|clip view|color well|color-panel|combo box( item)?|control|data( (cell|column|item|row|source))?|default entry|dialog reply|document|drag info|drawer|event|font(-panel)?|formatter|image( (cell|view))?|matrix|menu( item)?|item|movie( view)?|open-panel|outline view|panel|pasteboard|plugin|popup button|progress indicator|responder|save-panel|scroll view|secure text field( cell)?|slider|sound|split view|stepper|tab view( item)?|table( (column|header cell|header view|view))|text( (field( cell)?|view))?|toolbar( item)?|user-defaults|view|window)s?\b">
|
||||
<rule
|
||||
pattern="\b(action cell|alert reply|application|box|browser( cell)?|bundle|button( cell)?|cell|clip view|color well|color-panel|combo box( item)?|control|data( (cell|column|item|row|source))?|default entry|dialog reply|document|drag info|drawer|event|font(-panel)?|formatter|image( (cell|view))?|matrix|menu( item)?|item|movie( view)?|open-panel|outline view|panel|pasteboard|plugin|popup button|progress indicator|responder|save-panel|scroll view|secure text field( cell)?|slider|sound|split view|stepper|tab view( item)?|table( (column|header cell|header view|view))|text( (field( cell)?|view))?|toolbar( item)?|user-defaults|view|window)s?\b"
|
||||
>
|
||||
<token type="NameBuiltin" />
|
||||
</rule>
|
||||
<rule pattern="\b(animate|append|call method|center|close drawer|close panel|display|display alert|display dialog|display panel|go|hide|highlight|increment|item for|load image|load movie|load nib|load panel|load sound|localized string|lock focus|log|open drawer|path for|pause|perform action|play|register|resume|scroll|select( all)?|show|size to fit|start|step back|step forward|stop|synchronize|unlock focus|update)\b">
|
||||
<rule
|
||||
pattern="\b(animate|append|call method|center|close drawer|close panel|display|display alert|display dialog|display panel|go|hide|highlight|increment|item for|load image|load movie|load nib|load panel|load sound|localized string|lock focus|log|open drawer|path for|pause|perform action|play|register|resume|scroll|select( all)?|show|size to fit|start|step back|step forward|stop|synchronize|unlock focus|update)\b"
|
||||
>
|
||||
<token type="NameBuiltin" />
|
||||
</rule>
|
||||
<rule pattern="\b((in )?back of|(in )?front of|[0-9]+(st|nd|rd|th)|first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth|after|back|before|behind|every|front|index|last|middle|some|that|through|thru|where|whose)\b">
|
||||
<rule
|
||||
pattern="\b((in )?back of|(in )?front of|[0-9]+(st|nd|rd|th)|first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth|after|back|before|behind|every|front|index|last|middle|some|that|through|thru|where|whose)\b"
|
||||
>
|
||||
<token type="NameBuiltin" />
|
||||
</rule>
|
||||
<rule pattern=""(\\\\|\\"|[^"])*"">
|
||||
|
||||
2
vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arangodb_aql.xml
generated
vendored
2
vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arangodb_aql.xml
generated
vendored
@@ -152,7 +152,7 @@
|
||||
<rule pattern="(?-i)(?:CURRENT|NEW|OLD)\b">
|
||||
<token type="NameBuiltinPseudo"/>
|
||||
</rule>
|
||||
<rule pattern="(?:to_bool|to_number|to_string|to_array|to_list|is_null|is_bool|is_number|is_string|is_array|is_list|is_object|is_document|is_datestring|typename|json_stringify|json_parse|concat|concat_separator|char_length|lower|upper|substring|substring_bytes|left|right|trim|reverse|contains|log|log2|log10|exp|exp2|sin|cos|tan|asin|acos|atan|atan2|radians|degrees|pi|regex_test|regex_replace|like|floor|ceil|round|abs|rand|sqrt|pow|length|count|min|max|average|avg|sum|product|median|variance_population|variance_sample|variance|percentile|bit_and|bit_or|bit_xor|bit_negate|bit_test|bit_popcount|bit_shift_left|bit_shift_right|bit_construct|bit_deconstruct|bit_to_string|bit_from_string|first|last|unique|outersection|interleave|in_range|jaccard|matches|merge|merge_recursive|has|attributes|keys|values|unset|unset_recursive|keep|keep_recursive|near|within|within_rectangle|is_in_polygon|distance|fulltext|stddev_sample|stddev_population|stddev|slice|nth|position|contains_array|translate|zip|call|apply|push|append|pop|shift|unshift|remove_value|remove_values|remove_nth|replace_nth|date_now|date_timestamp|date_iso8601|date_dayofweek|date_year|date_month|date_day|date_hour|date_minute|date_second|date_millisecond|date_dayofyear|date_isoweek|date_isoweekyear|date_leapyear|date_quarter|date_days_in_month|date_trunc|date_round|date_add|date_subtract|date_diff|date_compare|date_format|date_utctolocal|date_localtoutc|date_timezone|date_timezones|fail|passthru|v8|sleep|schema_get|schema_validate|shard_id|version|noopt|noeval|not_null|first_list|first_document|parse_identifier|current_user|current_database|collection_count|pregel_result|collections|document|decode_rev|range|union|union_distinct|minus|intersection|flatten|is_same_collection|check_document|ltrim|rtrim|find_first|find_last|split|substitute|ipv4_to_number|ipv4_from_number|is_ipv4|md5|sha1|sha256|sha512|crc32|fnv64|hash|random_token|to_base64|to_hex|encode_uri_component|soundex|assert|warn|is_key|sorted|sorted_unique|count_distinct|count_unique|levenshtein_distance|levenshtein_match|regex_matches|regex_split|ngram_match|ngram_similarity|ngram_positional_similarity|uuid|tokens|exists|starts_with|phrase|min_match|bm25|tfidf|boost|analyzer|offset_info|value|cosine_similarity|decay_exp|decay_gauss|decay_linear|l1_distance|l2_distance|minhash|minhash_count|minhash_error|minhash_match|geo_point|geo_multipoint|geo_polygon|geo_multipolygon|geo_linestring|geo_multilinestring|geo_contains|geo_intersects|geo_equals|geo_distance|geo_area|geo_in_range)(?=\s*\()">
|
||||
<rule pattern="(?:to_bool|to_number|to_char|to_string|to_array|to_list|is_null|is_bool|is_number|is_string|is_array|is_list|is_object|is_document|is_datestring|typename|json_stringify|json_parse|concat|concat_separator|char_length|lower|upper|substring|substring_bytes|left|right|trim|reverse|repeat|contains|log|log2|log10|exp|exp2|sin|cos|tan|asin|acos|atan|atan2|radians|degrees|pi|regex_test|regex_replace|like|floor|ceil|round|abs|rand|random|sqrt|pow|length|count|min|max|average|avg|sum|product|median|variance_population|variance_sample|variance|percentile|bit_and|bit_or|bit_xor|bit_negate|bit_test|bit_popcount|bit_shift_left|bit_shift_right|bit_construct|bit_deconstruct|bit_to_string|bit_from_string|first|last|unique|outersection|interleave|in_range|jaccard|matches|merge|merge_recursive|has|attributes|keys|values|entries|unset|unset_recursive|keep|keep_recursive|near|within|within_rectangle|is_in_polygon|distance|fulltext|stddev_sample|stddev_population|stddev|slice|nth|position|contains_array|translate|zip|call|apply|push|append|pop|shift|unshift|remove_value|remove_values|remove_nth|replace_nth|date_now|date_timestamp|date_iso8601|date_dayofweek|date_year|date_month|date_day|date_hour|date_minute|date_second|date_millisecond|date_dayofyear|date_isoweek|date_isoweekyear|date_leapyear|date_quarter|date_days_in_month|date_trunc|date_round|date_add|date_subtract|date_diff|date_compare|date_format|date_utctolocal|date_localtoutc|date_timezone|date_timezones|fail|passthru|v8|sleep|schema_get|schema_validate|shard_id|version|noopt|noeval|not_null|first_list|first_document|parse_identifier|parse_collection|parse_key|current_user|current_database|collection_count|pregel_result|collections|document|decode_rev|range|union|union_distinct|minus|intersection|flatten|is_same_collection|check_document|ltrim|rtrim|find_first|find_last|split|substitute|ipv4_to_number|ipv4_from_number|is_ipv4|md5|sha1|sha256|sha512|crc32|fnv64|hash|random_token|to_base64|to_hex|encode_uri_component|soundex|assert|warn|is_key|sorted|sorted_unique|count_distinct|count_unique|levenshtein_distance|levenshtein_match|regex_matches|regex_split|ngram_match|ngram_similarity|ngram_positional_similarity|uuid|tokens|exists|starts_with|phrase|min_match|bm25|tfidf|boost|analyzer|offset_info|value|cosine_similarity|decay_exp|decay_gauss|decay_linear|l1_distance|l2_distance|minhash|minhash_count|minhash_error|minhash_match|geo_point|geo_multipoint|geo_polygon|geo_multipolygon|geo_linestring|geo_multilinestring|geo_contains|geo_intersects|geo_equals|geo_distance|geo_area|geo_in_range)(?=\s*\()">
|
||||
<token type="NameFunction"/>
|
||||
</rule>
|
||||
<rule pattern=""">
|
||||
|
||||
29
vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arduino.xml
generated
vendored
29
vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arduino.xml
generated
vendored
@@ -97,7 +97,9 @@
|
||||
</rule>
|
||||
</state>
|
||||
<state name="statements">
|
||||
<rule pattern="(reinterpret_cast|static_assert|dynamic_cast|thread_local|static_cast|const_cast|protected|constexpr|namespace|restrict|noexcept|override|operator|typename|template|explicit|decltype|nullptr|private|alignof|virtual|mutable|alignas|typeid|friend|throws|export|public|delete|final|using|throw|catch|this|try|new)\b">
|
||||
<rule
|
||||
pattern="(reinterpret_cast|static_assert|dynamic_cast|thread_local|static_cast|const_cast|protected|constexpr|namespace|restrict|noexcept|override|operator|typename|template|explicit|decltype|nullptr|private|alignof|virtual|mutable|alignas|typeid|friend|throws|export|public|delete|final|using|throw|catch|this|try|new)\b"
|
||||
>
|
||||
<token type="Keyword" />
|
||||
</rule>
|
||||
<rule pattern="char(16_t|32_t)\b">
|
||||
@@ -106,7 +108,6 @@
|
||||
<rule pattern="(class)\b">
|
||||
<bygroups>
|
||||
<token type="Keyword" />
|
||||
<token type="Text"/>
|
||||
</bygroups>
|
||||
<push state="classname" />
|
||||
</rule>
|
||||
@@ -167,25 +168,35 @@
|
||||
<rule pattern="[()\[\],.]">
|
||||
<token type="Punctuation" />
|
||||
</rule>
|
||||
<rule pattern="(restricted|volatile|continue|register|default|typedef|struct|extern|switch|sizeof|static|return|union|while|const|break|goto|enum|else|case|auto|for|asm|if|do)\b">
|
||||
<rule
|
||||
pattern="(restricted|volatile|continue|register|default|typedef|struct|extern|switch|sizeof|static|return|union|while|const|break|goto|enum|else|case|auto|for|asm|if|do)\b"
|
||||
>
|
||||
<token type="Keyword" />
|
||||
</rule>
|
||||
<rule pattern="(_Bool|_Complex|_Imaginary|array|atomic_bool|atomic_char|atomic_int|atomic_llong|atomic_long|atomic_schar|atomic_short|atomic_uchar|atomic_uint|atomic_ullong|atomic_ulong|atomic_ushort|auto|bool|boolean|BooleanVariables|Byte|byte|Char|char|char16_t|char32_t|class|complex|Const|const|const_cast|delete|double|dynamic_cast|enum|explicit|extern|Float|float|friend|inline|Int|int|int16_t|int32_t|int64_t|int8_t|Long|long|new|NULL|null|operator|private|PROGMEM|protected|public|register|reinterpret_cast|short|signed|sizeof|Static|static|static_cast|String|struct|typedef|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|virtual|Void|void|Volatile|volatile|word)\b">
|
||||
<rule
|
||||
pattern="(_Bool|_Complex|_Imaginary|array|atomic_bool|atomic_char|atomic_int|atomic_llong|atomic_long|atomic_schar|atomic_short|atomic_uchar|atomic_uint|atomic_ullong|atomic_ulong|atomic_ushort|auto|bool|boolean|BooleanVariables|Byte|byte|Char|char|char16_t|char32_t|class|complex|Const|const|const_cast|delete|double|dynamic_cast|enum|explicit|extern|Float|float|friend|inline|Int|int|int16_t|int32_t|int64_t|int8_t|Long|long|new|NULL|null|operator|private|PROGMEM|protected|public|register|reinterpret_cast|short|signed|sizeof|Static|static|static_cast|String|struct|typedef|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|virtual|Void|void|Volatile|volatile|word)\b"
|
||||
>
|
||||
<token type="KeywordType" />
|
||||
</rule>
|
||||
<rule pattern="(and|final|If|Loop|loop|not|or|override|setup|Setup|throw|try|xor)\b">
|
||||
<token type="Keyword" />
|
||||
</rule>
|
||||
<rule pattern="(ANALOG_MESSAGE|BIN|CHANGE|DEC|DEFAULT|DIGITAL_MESSAGE|EXTERNAL|FALLING|FIRMATA_STRING|HALF_PI|HEX|HIGH|INPUT|INPUT_PULLUP|INTERNAL|INTERNAL1V1|INTERNAL1V1|INTERNAL2V56|INTERNAL2V56|LED_BUILTIN|LED_BUILTIN_RX|LED_BUILTIN_TX|LOW|LSBFIRST|MSBFIRST|OCT|OUTPUT|PI|REPORT_ANALOG|REPORT_DIGITAL|RISING|SET_PIN_MODE|SYSEX_START|SYSTEM_RESET|TWO_PI)\b">
|
||||
<rule
|
||||
pattern="(ANALOG_MESSAGE|BIN|CHANGE|DEC|DEFAULT|DIGITAL_MESSAGE|EXTERNAL|FALLING|FIRMATA_STRING|HALF_PI|HEX|HIGH|INPUT|INPUT_PULLUP|INTERNAL|INTERNAL1V1|INTERNAL1V1|INTERNAL2V56|INTERNAL2V56|LED_BUILTIN|LED_BUILTIN_RX|LED_BUILTIN_TX|LOW|LSBFIRST|MSBFIRST|OCT|OUTPUT|PI|REPORT_ANALOG|REPORT_DIGITAL|RISING|SET_PIN_MODE|SYSEX_START|SYSTEM_RESET|TWO_PI)\b"
|
||||
>
|
||||
<token type="KeywordConstant" />
|
||||
</rule>
|
||||
<rule pattern="(boolean|const|byte|word|string|String|array)\b">
|
||||
<token type="NameVariable" />
|
||||
</rule>
|
||||
<rule pattern="(Keyboard|KeyboardController|MouseController|SoftwareSerial|EthernetServer|EthernetClient|LiquidCrystal|RobotControl|GSMVoiceCall|EthernetUDP|EsploraTFT|HttpClient|RobotMotor|WiFiClient|GSMScanner|FileSystem|Scheduler|GSMServer|YunClient|YunServer|IPAddress|GSMClient|GSMModem|Keyboard|Ethernet|Console|GSMBand|Esplora|Stepper|Process|WiFiUDP|GSM_SMS|Mailbox|USBHost|Firmata|PImage|Client|Server|GSMPIN|FileIO|Bridge|Serial|EEPROM|Stream|Mouse|Audio|Servo|File|Task|GPRS|WiFi|Wire|TFT|GSM|SPI|SD)\b">
|
||||
<rule
|
||||
pattern="(Keyboard|KeyboardController|MouseController|SoftwareSerial|EthernetServer|EthernetClient|LiquidCrystal|RobotControl|GSMVoiceCall|EthernetUDP|EsploraTFT|HttpClient|RobotMotor|WiFiClient|GSMScanner|FileSystem|Scheduler|GSMServer|YunClient|YunServer|IPAddress|GSMClient|GSMModem|Keyboard|Ethernet|Console|GSMBand|Esplora|Stepper|Process|WiFiUDP|GSM_SMS|Mailbox|USBHost|Firmata|PImage|Client|Server|GSMPIN|FileIO|Bridge|Serial|EEPROM|Stream|Mouse|Audio|Servo|File|Task|GPRS|WiFi|Wire|TFT|GSM|SPI|SD)\b"
|
||||
>
|
||||
<token type="NameClass" />
|
||||
</rule>
|
||||
<rule pattern="(abs|Abs|accept|ACos|acos|acosf|addParameter|analogRead|AnalogRead|analogReadResolution|AnalogReadResolution|analogReference|AnalogReference|analogWrite|AnalogWrite|analogWriteResolution|AnalogWriteResolution|answerCall|asin|ASin|asinf|atan|ATan|atan2|ATan2|atan2f|atanf|attach|attached|attachGPRS|attachInterrupt|AttachInterrupt|autoscroll|available|availableForWrite|background|beep|begin|beginPacket|beginSD|beginSMS|beginSpeaker|beginTFT|beginTransmission|beginWrite|bit|Bit|BitClear|bitClear|bitRead|BitRead|bitSet|BitSet|BitWrite|bitWrite|blink|blinkVersion|BSSID|buffer|byte|cbrt|cbrtf|Ceil|ceil|ceilf|changePIN|char|charAt|checkPIN|checkPUK|checkReg|circle|cityNameRead|cityNameWrite|clear|clearScreen|click|close|compareTo|compassRead|concat|config|connect|connected|constrain|Constrain|copysign|copysignf|cos|Cos|cosf|cosh|coshf|countryNameRead|countryNameWrite|createChar|cursor|debugPrint|degrees|Delay|delay|DelayMicroseconds|delayMicroseconds|detach|DetachInterrupt|detachInterrupt|DigitalPinToInterrupt|digitalPinToInterrupt|DigitalRead|digitalRead|DigitalWrite|digitalWrite|disconnect|display|displayLogos|drawBMP|drawCompass|encryptionType|end|endPacket|endSMS|endsWith|endTransmission|endWrite|equals|equalsIgnoreCase|exists|exitValue|Exp|exp|expf|fabs|fabsf|fdim|fdimf|fill|find|findUntil|float|floor|Floor|floorf|flush|fma|fmaf|fmax|fmaxf|fmin|fminf|fmod|fmodf|gatewayIP|get|getAsynchronously|getBand|getButton|getBytes|getCurrentCarrier|getIMEI|getKey|getModifiers|getOemKey|getPINUsed|getResult|getSignalStrength|getSocket|getVoiceCallStatus|getXChange|getYChange|hangCall|height|highByte|HighByte|home|hypot|hypotf|image|indexOf|int|interrupts|IPAddress|IRread|isActionDone|isAlpha|isAlphaNumeric|isAscii|isControl|isDigit|isDirectory|isfinite|isGraph|isHexadecimalDigit|isinf|isListening|isLowerCase|isnan|isPIN|isPressed|isPrintable|isPunct|isSpace|isUpperCase|isValid|isWhitespace|keyboardRead|keyPressed|keyReleased|knobRead|lastIndexOf|ldexp|ldexpf|leftToRight|length|line|lineFollowConfig|listen|listenOnLocalhost|loadImage|localIP|log|Log|log10|log10f|logf|long|lowByte|LowByte|lrint|lrintf|lround|lroundf|macAddress|maintain|map|Map|Max|max|messageAvailable|Micros|micros|millis|Millis|Min|min|mkdir|motorsStop|motorsWrite|mouseDragged|mouseMoved|mousePressed|mouseReleased|move|noAutoscroll|noBlink|noBuffer|noCursor|noDisplay|noFill|noInterrupts|NoInterrupts|noListenOnLocalhost|noStroke|noTone|NoTone|onReceive|onRequest|open|openNextFile|overflow|parseCommand|parseFloat|parseInt|parsePacket|pauseMode|peek|PinMode|pinMode|playFile|playMelody|point|pointTo|position|Pow|pow|powf|prepare|press|print|printFirmwareVersion|println|printVersion|process|processInput|PulseIn|pulseIn|pulseInLong|PulseInLong|put|radians|random|Random|randomSeed|RandomSeed|read|readAccelerometer|readBlue|readButton|readBytes|readBytesUntil|readGreen|readJoystickButton|readJoystickSwitch|readJoystickX|readJoystickY|readLightSensor|readMessage|readMicrophone|readNetworks|readRed|readSlider|readString|readStringUntil|readTemperature|ready|rect|release|releaseAll|remoteIP|remoteNumber|remotePort|remove|replace|requestFrom|retrieveCallingNumber|rewindDirectory|rightToLeft|rmdir|robotNameRead|robotNameWrite|round|roundf|RSSI|run|runAsynchronously|running|runShellCommand|runShellCommandAsynchronously|scanNetworks|scrollDisplayLeft|scrollDisplayRight|seek|sendAnalog|sendDigitalPortPair|sendDigitalPorts|sendString|sendSysex|Serial_Available|Serial_Begin|Serial_End|Serial_Flush|Serial_Peek|Serial_Print|Serial_Println|Serial_Read|serialEvent|setBand|setBitOrder|setCharAt|setClockDivider|setCursor|setDataMode|setDNS|setFirmwareVersion|setMode|setPINUsed|setSpeed|setTextSize|setTimeout|ShiftIn|shiftIn|ShiftOut|shiftOut|shutdown|signbit|sin|Sin|sinf|sinh|sinhf|size|sizeof|Sq|sq|Sqrt|sqrt|sqrtf|SSID|startLoop|startsWith|step|stop|stroke|subnetMask|substring|switchPIN|tan|Tan|tanf|tanh|tanhf|tempoWrite|text|toCharArray|toInt|toLowerCase|tone|Tone|toUpperCase|transfer|trim|trunc|truncf|tuneWrite|turn|updateIR|userNameRead|userNameWrite|voiceCall|waitContinue|width|WiFiServer|word|write|writeBlue|writeGreen|writeJSON|writeMessage|writeMicroseconds|writeRed|writeRGB|yield|Yield)\b">
|
||||
<rule
|
||||
pattern="(abs|Abs|accept|ACos|acos|acosf|addParameter|analogRead|AnalogRead|analogReadResolution|AnalogReadResolution|analogReference|AnalogReference|analogWrite|AnalogWrite|analogWriteResolution|AnalogWriteResolution|answerCall|asin|ASin|asinf|atan|ATan|atan2|ATan2|atan2f|atanf|attach|attached|attachGPRS|attachInterrupt|AttachInterrupt|autoscroll|available|availableForWrite|background|beep|begin|beginPacket|beginSD|beginSMS|beginSpeaker|beginTFT|beginTransmission|beginWrite|bit|Bit|BitClear|bitClear|bitRead|BitRead|bitSet|BitSet|BitWrite|bitWrite|blink|blinkVersion|BSSID|buffer|byte|cbrt|cbrtf|Ceil|ceil|ceilf|changePIN|char|charAt|checkPIN|checkPUK|checkReg|circle|cityNameRead|cityNameWrite|clear|clearScreen|click|close|compareTo|compassRead|concat|config|connect|connected|constrain|Constrain|copysign|copysignf|cos|Cos|cosf|cosh|coshf|countryNameRead|countryNameWrite|createChar|cursor|debugPrint|degrees|Delay|delay|DelayMicroseconds|delayMicroseconds|detach|DetachInterrupt|detachInterrupt|DigitalPinToInterrupt|digitalPinToInterrupt|DigitalRead|digitalRead|DigitalWrite|digitalWrite|disconnect|display|displayLogos|drawBMP|drawCompass|encryptionType|end|endPacket|endSMS|endsWith|endTransmission|endWrite|equals|equalsIgnoreCase|exists|exitValue|Exp|exp|expf|fabs|fabsf|fdim|fdimf|fill|find|findUntil|float|floor|Floor|floorf|flush|fma|fmaf|fmax|fmaxf|fmin|fminf|fmod|fmodf|gatewayIP|get|getAsynchronously|getBand|getButton|getBytes|getCurrentCarrier|getIMEI|getKey|getModifiers|getOemKey|getPINUsed|getResult|getSignalStrength|getSocket|getVoiceCallStatus|getXChange|getYChange|hangCall|height|highByte|HighByte|home|hypot|hypotf|image|indexOf|int|interrupts|IPAddress|IRread|isActionDone|isAlpha|isAlphaNumeric|isAscii|isControl|isDigit|isDirectory|isfinite|isGraph|isHexadecimalDigit|isinf|isListening|isLowerCase|isnan|isPIN|isPressed|isPrintable|isPunct|isSpace|isUpperCase|isValid|isWhitespace|keyboardRead|keyPressed|keyReleased|knobRead|lastIndexOf|ldexp|ldexpf|leftToRight|length|line|lineFollowConfig|listen|listenOnLocalhost|loadImage|localIP|log|Log|log10|log10f|logf|long|lowByte|LowByte|lrint|lrintf|lround|lroundf|macAddress|maintain|map|Map|Max|max|messageAvailable|Micros|micros|millis|Millis|Min|min|mkdir|motorsStop|motorsWrite|mouseDragged|mouseMoved|mousePressed|mouseReleased|move|noAutoscroll|noBlink|noBuffer|noCursor|noDisplay|noFill|noInterrupts|NoInterrupts|noListenOnLocalhost|noStroke|noTone|NoTone|onReceive|onRequest|open|openNextFile|overflow|parseCommand|parseFloat|parseInt|parsePacket|pauseMode|peek|PinMode|pinMode|playFile|playMelody|point|pointTo|position|Pow|pow|powf|prepare|press|print|printFirmwareVersion|println|printVersion|process|processInput|PulseIn|pulseIn|pulseInLong|PulseInLong|put|radians|random|Random|randomSeed|RandomSeed|read|readAccelerometer|readBlue|readButton|readBytes|readBytesUntil|readGreen|readJoystickButton|readJoystickSwitch|readJoystickX|readJoystickY|readLightSensor|readMessage|readMicrophone|readNetworks|readRed|readSlider|readString|readStringUntil|readTemperature|ready|rect|release|releaseAll|remoteIP|remoteNumber|remotePort|remove|replace|requestFrom|retrieveCallingNumber|rewindDirectory|rightToLeft|rmdir|robotNameRead|robotNameWrite|round|roundf|RSSI|run|runAsynchronously|running|runShellCommand|runShellCommandAsynchronously|scanNetworks|scrollDisplayLeft|scrollDisplayRight|seek|sendAnalog|sendDigitalPortPair|sendDigitalPorts|sendString|sendSysex|Serial_Available|Serial_Begin|Serial_End|Serial_Flush|Serial_Peek|Serial_Print|Serial_Println|Serial_Read|serialEvent|setBand|setBitOrder|setCharAt|setClockDivider|setCursor|setDataMode|setDNS|setFirmwareVersion|setMode|setPINUsed|setSpeed|setTextSize|setTimeout|ShiftIn|shiftIn|ShiftOut|shiftOut|shutdown|signbit|sin|Sin|sinf|sinh|sinhf|size|sizeof|Sq|sq|Sqrt|sqrt|sqrtf|SSID|startLoop|startsWith|step|stop|stroke|subnetMask|substring|switchPIN|tan|Tan|tanf|tanh|tanhf|tempoWrite|text|toCharArray|toInt|toLowerCase|tone|Tone|toUpperCase|transfer|trim|trunc|truncf|tuneWrite|turn|updateIR|userNameRead|userNameWrite|voiceCall|waitContinue|width|WiFiServer|word|write|writeBlue|writeGreen|writeJSON|writeMessage|writeMicroseconds|writeRed|writeRGB|yield|Yield)\b"
|
||||
>
|
||||
<token type="NameFunction" />
|
||||
</rule>
|
||||
<rule pattern="(typename|__inline|restrict|_inline|thread|inline|naked)\b">
|
||||
@@ -194,7 +205,9 @@
|
||||
<rule pattern="(__m(128i|128d|128|64))\b">
|
||||
<token type="KeywordReserved" />
|
||||
</rule>
|
||||
<rule pattern="__(forceinline|identifier|unaligned|declspec|fastcall|finally|stdcall|wchar_t|assume|except|int32|cdecl|int16|leave|based|raise|int64|noop|int8|w64|try|asm)\b">
|
||||
<rule
|
||||
pattern="__(forceinline|identifier|unaligned|declspec|fastcall|finally|stdcall|wchar_t|assume|except|int32|cdecl|int16|leave|based|raise|int64|noop|int8|w64|try|asm)\b"
|
||||
>
|
||||
<token type="KeywordReserved" />
|
||||
</rule>
|
||||
<rule pattern="(true|false|NULL)\b">
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user