Compare commits

...

57 Commits

Author SHA1 Message Date
Tobias Trabelsi
601cc245ef bump version
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is failing
2023-07-20 09:12:14 +02:00
Tobias Trabelsi
340bcd48fe
Merge pull request #46 from deblasis/fix/gitea_oauth2_app_confidential_client
All checks were successful
continuous-integration/drone/push Build is passing
Support `gitea_oauth2_app` `confidential_client` flag
2023-07-20 09:09:50 +02:00
Alessandro De Blasis
2d7147442b fix(oauth): updates 2023-07-19 19:56:50 +00:00
Tobias Trabelsi
ed32470b17
Merge pull request #48 from Lerentis/feature/#47/list-all-org-repos
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is failing
2023-07-19 20:54:36 +02:00
483bda1033
added possibility to list all repos of an organisation 2023-07-19 20:52:36 +02:00
Tobias Trabelsi
48f5c3ee3c
Merge pull request #45 from Lerentis/dependabot/go_modules/github.com/hashicorp/terraform-plugin-docs-0.16.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-07-19 19:47:43 +02:00
Alessandro De Blasis
c707cba22e fix(gitea_oauth_app): added missing createoptions and resourcedata 2023-07-13 11:32:30 +00:00
Alessandro De Blasis
5b14a5d789 docs(oauth2_app): docs 2023-07-11 21:19:53 +00:00
Alessandro De Blasis
707443c6d2 feat(gitea_oauth_app): support 2023-07-11 21:18:08 +00:00
dependabot[bot]
04160fa7a3
Bump github.com/hashicorp/terraform-plugin-docs from 0.15.0 to 0.16.0
Bumps [github.com/hashicorp/terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs) from 0.15.0 to 0.16.0.
- [Release notes](https://github.com/hashicorp/terraform-plugin-docs/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-docs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-docs/compare/v0.15.0...v0.16.0)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-docs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 20:16:39 +00:00
Tobias Trabelsi
c1ba34b248 fix deprecated goreleaser flag
All checks were successful
continuous-integration/drone/push Build is passing
2023-07-04 11:43:37 +02:00
Tobias Trabelsi
0d09d97866 bump version
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is failing
2023-07-04 11:35:15 +02:00
Tobias Trabelsi
b3f93373d0
Merge pull request #38 from Lerentis/Lerentis/issue35
All checks were successful
continuous-integration/drone/push Build is passing
potential fix for #35
2023-07-04 10:40:44 +02:00
Tobias Trabelsi
58498b616b
Merge pull request #43 from Lerentis/dependabot/go_modules/github.com/hashicorp/terraform-plugin-docs-0.15.0
Bump github.com/hashicorp/terraform-plugin-docs from 0.14.1 to 0.15.0
2023-07-04 10:40:11 +02:00
dependabot[bot]
4e94047737
Bump github.com/hashicorp/terraform-plugin-docs from 0.14.1 to 0.15.0
Bumps [github.com/hashicorp/terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs) from 0.14.1 to 0.15.0.
- [Release notes](https://github.com/hashicorp/terraform-plugin-docs/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-docs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-docs/compare/v0.14.1...v0.15.0)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-docs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-04 08:39:56 +00:00
Tobias Trabelsi
425434baa8
Merge pull request #42 from Lerentis/dependabot/github_actions/goreleaser/goreleaser-action-4.3.0
Bump goreleaser/goreleaser-action from 4.2.0 to 4.3.0
2023-07-04 10:39:14 +02:00
dependabot[bot]
7f04ccd8f8
Bump goreleaser/goreleaser-action from 4.2.0 to 4.3.0
Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](https://github.com/goreleaser/goreleaser-action/compare/v4.2.0...v4.3.0)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-04 08:39:00 +00:00
Tobias Trabelsi
e8584b0270
Merge pull request #44 from Lerentis/dependabot/go_modules/github.com/hashicorp/terraform-plugin-sdk/v2-2.27.0
Bump github.com/hashicorp/terraform-plugin-sdk/v2 from 2.26.1 to 2.27.0
2023-07-04 10:37:55 +02:00
dependabot[bot]
910ccdb092
Bump github.com/hashicorp/terraform-plugin-sdk/v2 from 2.26.1 to 2.27.0
Bumps [github.com/hashicorp/terraform-plugin-sdk/v2](https://github.com/hashicorp/terraform-plugin-sdk) from 2.26.1 to 2.27.0.
- [Release notes](https://github.com/hashicorp/terraform-plugin-sdk/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-sdk/compare/v2.26.1...v2.27.0)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-sdk/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-03 20:21:30 +00:00
Tobias Trabelsi
b2403e2569
Merge pull request #40 from ultimania/feature/non-mirror-migration
Some checks reported errors
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build encountered an error
Fixed conditions of repository migration
2023-05-31 09:26:02 +02:00
ultimania
98867f2830 add example for origin migration 2023-05-31 10:56:18 +09:00
ultimania
948b20a6d2 fixed conditions of migration 2023-05-31 08:54:45 +09:00
Tobias Trabelsi
83a0cbf14c fallback on resource data on buggy gitea versions
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-17 10:27:17 +02:00
Tobias Trabelsi
71caf4430b potential fix for #35 2023-05-17 10:14:55 +02:00
Tobias Trabelsi
bc28fe186f
Merge pull request #37 from yamadayutaka/feature/team_repositories
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is failing
implement repositories attribute to gitea_team
2023-05-17 09:48:10 +02:00
Tobias Trabelsi
19062e27f0 transparent errors
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2023-05-17 09:34:11 +02:00
YAMADA Yutaka
322ad2d3c4 add log output on error 2023-05-17 00:48:25 +00:00
YAMADA Yutaka
9e34636c29 Bump the version from 0.12.3 to 0.13.0 2023-05-16 07:58:50 +00:00
YAMADA Yutaka
b4b13dc3ca implement repositories attribute of gitea_team 2023-05-15 03:22:29 +00:00
Tobias Trabelsi
e5a6132b9d
Merge pull request #34 from Lerentis/dependabot/github_actions/crazy-max/ghaction-import-gpg-5.3.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-10 10:46:32 +02:00
dependabot[bot]
d71cbbd0b6
Bump crazy-max/ghaction-import-gpg from 5.2.0 to 5.3.0
Bumps [crazy-max/ghaction-import-gpg](https://github.com/crazy-max/ghaction-import-gpg) from 5.2.0 to 5.3.0.
- [Release notes](https://github.com/crazy-max/ghaction-import-gpg/releases)
- [Commits](https://github.com/crazy-max/ghaction-import-gpg/compare/v5.2.0...v5.3.0)

---
updated-dependencies:
- dependency-name: crazy-max/ghaction-import-gpg
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 21:01:02 +00:00
Tobias Trabelsi
0a85957c50 #26 document codeberg not allowing pull mirrors
Some checks are pending
continuous-integration/drone/tag Build is running
continuous-integration/drone/push Build is passing
fixed permission failure in gite_repository
2023-04-21 13:23:18 +02:00
Tobias Trabelsi
f87515a453
Merge pull request #32 from Lerentis/dependabot/go_modules/github.com/hashicorp/terraform-plugin-sdk/v2-2.26.1
All checks were successful
continuous-integration/drone/push Build is passing
Bump github.com/hashicorp/terraform-plugin-sdk/v2 from 2.26.0 to 2.26.1
2023-03-28 10:48:35 +02:00
dependabot[bot]
0e8aa2bf9b
Bump github.com/hashicorp/terraform-plugin-sdk/v2 from 2.26.0 to 2.26.1
Bumps [github.com/hashicorp/terraform-plugin-sdk/v2](https://github.com/hashicorp/terraform-plugin-sdk) from 2.26.0 to 2.26.1.
- [Release notes](https://github.com/hashicorp/terraform-plugin-sdk/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-sdk/compare/v2.26.0...v2.26.1)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-sdk/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-27 21:02:54 +00:00
Tobias Trabelsi
1162650a73
Merge pull request #29 from Lerentis/dependabot/go_modules/github.com/hashicorp/terraform-plugin-docs-0.14.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-21 16:09:50 +01:00
dependabot[bot]
abc332958b
Bump github.com/hashicorp/terraform-plugin-docs from 0.13.0 to 0.14.1
Bumps [github.com/hashicorp/terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs) from 0.13.0 to 0.14.1.
- [Release notes](https://github.com/hashicorp/terraform-plugin-docs/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-docs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-docs/compare/v0.13.0...v0.14.1)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-docs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-21 15:09:33 +00:00
Tobias Trabelsi
6ce5f8bf9f
Merge pull request #30 from Lerentis/dependabot/github_actions/actions/setup-go-4
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-21 16:08:04 +01:00
Tobias Trabelsi
1c80699599
Merge pull request #31 from Lerentis/dependabot/go_modules/github.com/hashicorp/terraform-plugin-sdk/v2-2.26.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-21 16:05:12 +01:00
dependabot[bot]
84c9110a24
Bump github.com/hashicorp/terraform-plugin-sdk/v2 from 2.24.1 to 2.26.0
Bumps [github.com/hashicorp/terraform-plugin-sdk/v2](https://github.com/hashicorp/terraform-plugin-sdk) from 2.24.1 to 2.26.0.
- [Release notes](https://github.com/hashicorp/terraform-plugin-sdk/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-sdk/compare/v2.24.1...v2.26.0)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-sdk/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-20 20:25:53 +00:00
dependabot[bot]
ad2692136f
Bump actions/setup-go from 3 to 4
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3 to 4.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-20 20:22:19 +00:00
4f33464489
version bump
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2023-02-19 11:47:06 +01:00
2c787bd532 Fixed typo in repo data source
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-17 22:40:28 +00:00
feacbf5a3f update goreleaser version
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-31 19:40:16 +00:00
d6160c596b
correct version in docs
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2023-01-28 22:51:49 +01:00
9799416352
fixed org vanashing
All checks were successful
continuous-integration/drone/push Build is passing
fixed regression of  v0.11.1
2023-01-28 22:49:54 +01:00
8095c2a513
prepare next release
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2023-01-04 19:15:00 +01:00
Tobias Trabelsi
14c1a11417
Merge pull request #21 from martin31821/feature/deploykey
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2023-01-04 19:08:30 +01:00
Martin Koppehel
8a805faa72
Add docs 2023-01-04 10:10:45 +01:00
Martin Koppehel
32ad02fa73
Implement deploy_key resource 2023-01-03 20:29:22 +01:00
edd03aca2f
try to publish sbom with next release
All checks were successful
continuous-integration/drone/push Build is passing
2022-12-24 18:37:41 +01:00
0fe94d7dc1
bump version to include updates
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2022-12-24 18:04:13 +01:00
dependabot[bot]
d6f60fb0a7
Bump actions/setup-go from 2 to 3
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 2 to 3.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-24 18:04:13 +01:00
dependabot[bot]
282cd097f9
Bump github.com/hashicorp/terraform-plugin-sdk/v2 from 2.20.0 to 2.24.1
Bumps [github.com/hashicorp/terraform-plugin-sdk/v2](https://github.com/hashicorp/terraform-plugin-sdk) from 2.20.0 to 2.24.1.
- [Release notes](https://github.com/hashicorp/terraform-plugin-sdk/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-sdk/compare/v2.20.0...v2.24.1)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-sdk/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-24 18:04:13 +01:00
dependabot[bot]
683a051502
Bump crazy-max/ghaction-import-gpg from 5.0.0 to 5.2.0
Bumps [crazy-max/ghaction-import-gpg](https://github.com/crazy-max/ghaction-import-gpg) from 5.0.0 to 5.2.0.
- [Release notes](https://github.com/crazy-max/ghaction-import-gpg/releases)
- [Changelog](https://github.com/crazy-max/ghaction-import-gpg/blob/v5.2.0/CHANGELOG.md)
- [Commits](https://github.com/crazy-max/ghaction-import-gpg/compare/v5.0.0...v5.2.0)

---
updated-dependencies:
- dependency-name: crazy-max/ghaction-import-gpg
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-24 18:04:13 +01:00
dependabot[bot]
32278f74cc
Bump goreleaser/goreleaser-action from 3.0.0 to 4.1.0
Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 3.0.0 to 4.1.0.
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](https://github.com/goreleaser/goreleaser-action/compare/v3.0.0...v4.1.0)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-24 18:04:13 +01:00
dependabot[bot]
b4859cda6b
Bump github.com/hashicorp/terraform-plugin-docs from 0.7.0 to 0.13.0
Bumps [github.com/hashicorp/terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs) from 0.7.0 to 0.13.0.
- [Release notes](https://github.com/hashicorp/terraform-plugin-docs/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-docs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-docs/compare/v0.7.0...v0.13.0)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-docs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-18 17:14:23 +00:00
Tobias Trabelsi
ad07770b6b
Create dependabot.yml 2022-12-18 18:12:56 +01:00
1326 changed files with 121546 additions and 22197 deletions

View File

@ -30,6 +30,7 @@ steps:
- name: build
image: goreleaser/goreleaser
commands:
- curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin v0.64.0
- goreleaser build --snapshot
when:
event:
@ -59,6 +60,7 @@ steps:
GPG_PRIVATE_KEY_BASE64:
from_secret: GPG_PRIVATE_KEY_BASE64
commands:
- curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin v0.64.0
- apk add gpg-agent
- gpg-agent --daemon --default-cache-ttl 7200
- echo $GPG_PRIVATE_KEY_BASE64 | base64 -d | gpg --import --batch --no-tty

15
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,15 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@ -18,30 +18,29 @@ jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
-
name: Checkout
- name: Checkout
uses: actions/checkout@v3
-
name: Unshallow
- name: Unshallow
run: git fetch --prune --unshallow
-
name: Set up Go
uses: actions/setup-go@v2
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.18
-
name: Import GPG key
- name: Import GPG key
id: import_gpg
uses: crazy-max/ghaction-import-gpg@v5.0.0
uses: crazy-max/ghaction-import-gpg@v5.3.0
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.PASSPHRASE }}
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v3.0.0
- name: setup-syft
run: |
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | \
sh -s -- -b /usr/local/bin v0.64.0
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v4.3.0
with:
version: latest
args: release --rm-dist
args: release --clean
env:
GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}
# GitHub sets this automatically

View File

@ -41,6 +41,8 @@ checksum:
name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json'
name_template: '{{ .ProjectName }}_{{ .Version }}_SHA256SUMS'
algorithm: sha256
sboms:
- artifacts: archive
signs:
- artifacts: checksum
args:

View File

@ -1,9 +1,11 @@
TEST?=./gitea
GOFMT_FILES?=$$(find . -name '*.go' |grep -v vendor)
ARCH?=$$(uname -m)
KERNEL?=$$(uname -s | tr '[:upper:]' '[:lower:]')
GOFMT ?= gofmt -s
VERSION = 0.11.1
VERSION = 0.16.0
test: fmt-check
go test -i $(TEST) || exit 1
@ -34,8 +36,8 @@ build:
go build -ldflags="-X 'main.Version=${VERSION}'" -o terraform-provider-gitea_${VERSION}
install: build
@echo installing to
@echo ~/.terraform.d/plugins/terraform.local/lerentis/gitea/${VERSION}/linux_amd64/terraform-provider-gitea_${VERSION}
@mkdir -p ~/.terraform.d/plugins/terraform.local/lerentis/gitea/${VERSION}/linux_amd64
@mv terraform-provider-gitea_${VERSION} ~/.terraform.d/plugins/terraform.local/lerentis/gitea/${VERSION}/linux_amd64/terraform-provider-gitea_${VERSION}
@echo ~/.terraform.d/plugins/terraform.local/lerentis/gitea/${VERSION}/${KERNEL}_${ARCH}/terraform-provider-gitea_${VERSION}
@mkdir -p ~/.terraform.d/plugins/terraform.local/lerentis/gitea/${VERSION}/${KERNEL}_${ARCH}
@mv terraform-provider-gitea_${VERSION} ~/.terraform.d/plugins/terraform.local/lerentis/gitea/${VERSION}/${KERNEL}_${ARCH}/terraform-provider-gitea_${VERSION}
doc:
tfplugindocs

View File

@ -17,7 +17,7 @@ terraform {
required_providers {
gitea = {
source = "Lerentis/gitea"
version = "0.11.1"
version = "0.16.0"
}
}
}

View File

@ -17,7 +17,7 @@ terraform {
required_providers {
gitea = {
source = "Lerentis/gitea"
version = "0.11.1"
version = "0.16.0"
}
}
}

View File

@ -20,6 +20,10 @@ Handling [gitea oauth application](https://docs.gitea.io/en-us/oauth2-provider/)
- `name` (String) OAuth Application name
- `redirect_uris` (Set of String) Accepted redirect URIs
### Optional
- `confidential_client` (Boolean) If set to false, it will be a public client (PKCE will be required)
### Read-Only
- `client_id` (String) OAuth2 Application client id

View File

@ -46,5 +46,6 @@ resource "gitea_repository" "org_repo" {
- `avatar_url` (String)
- `id` (String) The ID of this resource.
- `repos` (List of String) List of all Repositories that are part of this organisation

View File

@ -7,6 +7,7 @@ description: |-
Per default this repository will be initializiled with the provided configuration (gitignore, License etc.).
If the username property is set to a organisation name, the provider will try to look if this organisation exists and create the repository under the organisation scope.
Repository migrations have some properties that are not available to regular repositories. These are all prefixed with migration_.
Codeberg.org does currently not allow mirrors to be created. See FAQ Section of CodeBerg for more information: https://docs.codeberg.org/getting-started/faq/#why-am-i-not-allowed-to-set-up-an-automatic-mirror
---
# gitea_repository (Resource)
@ -17,6 +18,7 @@ Per default this repository will be initializiled with the provided configuratio
If the `username` property is set to a organisation name, the provider will try to look if this organisation exists and create the repository under the organisation scope.
Repository migrations have some properties that are not available to regular repositories. These are all prefixed with `migration_`.
Codeberg.org does currently not allow mirrors to be created. See FAQ Section of CodeBerg for more information: https://docs.codeberg.org/getting-started/faq/#why-am-i-not-allowed-to-set-up-an-automatic-mirror
## Example Usage
@ -39,6 +41,16 @@ resource "gitea_repository" "mirror" {
migration_service = "gitea"
migration_service_auth_token = var.gitea_mirror_token
}
resource "gitea_repository" "clone" {
username = "lerentis"
name = "terraform-provider-gitea-clone"
description = "Clone of Terraform Provider"
mirror = false
migration_clone_address = "https://git.uploadfilter24.eu/lerentis/terraform-provider-gitea.git"
migration_service = "gitea"
migration_service_auth_token = var.gitea_clone_token
}
```
<!-- schema generated by tfplugindocs -->
@ -92,14 +104,14 @@ Need to exist in the gitea instance
### Read-Only
- `created` (String)
- `clone_url` (String)
- `created` (String)
- `html_url` (String)
- `id` (String) The ID of this resource.
- `ssh_url` (String)
- `permission_admin` (Boolean)
- `permission_pull` (Boolean)
- `permission_push` (Boolean)
- `ssh_url` (String)
- `updated` (String)

View File

@ -0,0 +1,63 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "gitea_repository_key Resource - terraform-provider-gitea"
subcategory: ""
description: |-
gitea_repository_key manages a deploy key for a single gitea_repository.
Every key needs a unique name and unique key, i.e. no key can be added twice to the same repo
---
# gitea_repository_key (Resource)
`gitea_repository_key` manages a deploy key for a single gitea_repository.
Every key needs a unique name and unique key, i.e. no key can be added twice to the same repo
## Example Usage
```terraform
terraform {
required_providers {
tls = {
source = "hashicorp/tls"
version = "4.0.4"
}
}
}
resource "tls_private_key" "example" {
type = "RSA"
rsa_bits = 4096
}
resource "gitea_repository" "example" {
name = "example"
private = true
}
resource "gitea_repository_key" "example" {
repository = gitea_repository.example.id
title = "Example Deploy Key"
read_only = true
key = tls_private_key.example.public_key_openssh
}
```
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `key` (String) Armored SSH key to add
- `repository` (Number) The ID of the repository where the deploy key belongs to
- `title` (String) Name of the deploy key
### Optional
- `read_only` (Boolean) Whether this key has read or read/write access
### Read-Only
- `id` (String) The ID of this resource.

View File

@ -34,6 +34,26 @@ resource "gitea_team" "test_team" {
permission = "write"
members = [gitea_user.test.username]
}
resource "gitea_repository" "test" {
username = gitea_org.test_org.name
name = "test"
private = true
issue_labels = "Default"
license = "MIT"
gitignores = "Go"
}
resource "gitea_team" "test_team_restricted" {
name = "Restricted Devs"
organisation = gitea_org.test_org.name
description = "Restricted Devs of Test Org"
permission = "write"
members = [gitea_user.test.username]
include_all_repositories = false
repositories = [gitea_repository.test.name]
}
```
<!-- schema generated by tfplugindocs -->
@ -52,6 +72,7 @@ resource "gitea_team" "test_team" {
- `members` (List of String) List of Users that should be part of this team
- `permission` (String) Permissions associated with this Team
Can be `none`, `read`, `write`, `admin` or `owner`
- `repositories` (List of String) List of Repositories that should be part of this team
- `units` (String) List of types of Repositories that should be allowed to be created from Team members.
Can be `repo.code`, `repo.issues`, `repo.ext_issues`, `repo.wiki`, `repo.pulls`, `repo.releases`, `repo.projects` and/or `repo.ext_wiki`

View File

@ -101,7 +101,37 @@ resource "gitea_token" "test_token" {
name = "test-token"
}
resource "gitea_repository" "test_existing_user" {
username = "testuser2"
name = "testExistingUser"
private = true
issue_labels = "Default"
license = "MIT"
gitignores = "Go"
}
//resource "gitea_repository" "test_bs_user" {
// username = "manualTest"
// name = "testBullshitUser"
// private = true
// issue_labels = "Default"
// license = "MIT"
// gitignores = "Go"
//}
output "token" {
value = resource.gitea_token.test_token.token
sensitive = true
}
}
data "gitea_repo" "org_repos" {
name = each.key
username = gitea_org.org1.name
for_each = {
for repo in resource.gitea_org.org1.repos : repo => repo
}
}
output "repos" {
value = data.gitea_repo.org_repos["repo1-in-org1"].clone_url
}

View File

@ -2,7 +2,7 @@ terraform {
required_providers {
gitea = {
source = "terraform.local/lerentis/gitea"
version = "0.11.1"
version = "0.16.0"
}
}
}

View File

@ -2,7 +2,7 @@ terraform {
required_providers {
gitea = {
source = "Lerentis/gitea"
version = "0.11.1"
version = "0.16.0"
}
}
}

View File

@ -16,3 +16,13 @@ resource "gitea_repository" "mirror" {
migration_service = "gitea"
migration_service_auth_token = var.gitea_mirror_token
}
resource "gitea_repository" "clone" {
username = "lerentis"
name = "terraform-provider-gitea-clone"
description = "Clone of Terraform Provider"
mirror = false
migration_clone_address = "https://git.uploadfilter24.eu/lerentis/terraform-provider-gitea.git"
migration_service = "gitea"
migration_service_auth_token = var.gitea_clone_token
}

View File

@ -0,0 +1,25 @@
terraform {
required_providers {
tls = {
source = "hashicorp/tls"
version = "4.0.4"
}
}
}
resource "tls_private_key" "example" {
type = "RSA"
rsa_bits = 4096
}
resource "gitea_repository" "example" {
name = "example"
private = true
}
resource "gitea_repository_key" "example" {
repository = gitea_repository.example.id
title = "Example Deploy Key"
read_only = true
key = tls_private_key.example.public_key_openssh
}

View File

@ -19,3 +19,23 @@ resource "gitea_team" "test_team" {
permission = "write"
members = [gitea_user.test.username]
}
resource "gitea_repository" "test" {
username = gitea_org.test_org.name
name = "test"
private = true
issue_labels = "Default"
license = "MIT"
gitignores = "Go"
}
resource "gitea_team" "test_team_restricted" {
name = "Restricted Devs"
organisation = gitea_org.test_org.name
description = "Restricted Devs of Test Org"
permission = "write"
members = [gitea_user.test.username]
include_all_repositories = false
repositories = [gitea_repository.test.name]
}

View File

@ -116,7 +116,7 @@ func dataSourceGiteaRepoRead(d *schema.ResourceData, meta interface{}) error {
}
username := strings.ToLower(usernameData.(string))
nameData, nameOk := d.GetOk("username")
nameData, nameOk := d.GetOk("name")
if !nameOk {
return fmt.Errorf("name of repo must be passed")
}

View File

@ -75,14 +75,15 @@ func Provider() *schema.Provider {
"gitea_org": resourceGiteaOrg(),
// "gitea_team": resourceGiteaTeam(),
// "gitea_repo": resourceGiteaRepo(),
"gitea_user": resourceGiteaUser(),
"gitea_oauth2_app": resourceGiteaOauthApp(),
"gitea_repository": resourceGiteaRepository(),
"gitea_fork": resourceGiteaFork(),
"gitea_public_key": resourceGiteaPublicKey(),
"gitea_team": resourceGiteaTeam(),
"gitea_git_hook": resourceGiteaGitHook(),
"gitea_token": resourceGiteaToken(),
"gitea_user": resourceGiteaUser(),
"gitea_oauth2_app": resourceGiteaOauthApp(),
"gitea_repository": resourceGiteaRepository(),
"gitea_fork": resourceGiteaFork(),
"gitea_public_key": resourceGiteaPublicKey(),
"gitea_team": resourceGiteaTeam(),
"gitea_git_hook": resourceGiteaGitHook(),
"gitea_token": resourceGiteaToken(),
"gitea_repository_key": resourceGiteaRepositoryKey(),
},
ConfigureFunc: providerConfigure,

View File

@ -8,10 +8,11 @@ import (
)
const (
oauth2KeyName string = "name"
oauth2KeyRedirectURIs string = "redirect_uris"
oauth2KeyClientId string = "client_id"
oauth2KeyClientSecret string = "client_secret"
oauth2KeyName string = "name"
oauth2KeyConfidentialClient string = "confidential_client"
oauth2KeyRedirectURIs string = "redirect_uris"
oauth2KeyClientId string = "client_id"
oauth2KeyClientSecret string = "client_secret"
)
func resourceGiteaOauthApp() *schema.Resource {
@ -37,6 +38,12 @@ func resourceGiteaOauthApp() *schema.Resource {
},
Description: "Accepted redirect URIs",
},
oauth2KeyConfidentialClient: {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "If set to false, it will be a public client (PKCE will be required)",
},
oauth2KeyClientId: {
Type: schema.TypeString,
Computed: true,
@ -89,9 +96,16 @@ func resourceOauth2AppUpcreate(d *schema.ResourceData, meta interface{}) (err er
return fmt.Errorf("attribute %s must be set and must be a string", oauth2KeyName)
}
confidentialClient, confidentialClientOk := d.Get(oauth2KeyConfidentialClient).(bool)
if !confidentialClientOk {
return fmt.Errorf("attribute %s must be set and must be a bool", oauth2KeyConfidentialClient)
}
opts := gitea.CreateOauth2Option{
Name: name,
RedirectURIs: redirectURIs,
Name: name,
ConfidentialClient: confidentialClient,
RedirectURIs: redirectURIs,
}
var oauth2 *gitea.Oauth2
@ -99,7 +113,7 @@ func resourceOauth2AppUpcreate(d *schema.ResourceData, meta interface{}) (err er
if d.IsNewResource() {
oauth2, _, err = client.CreateOauth2(opts)
} else {
oauth2, err := searchOauth2AppByClientId(client, d.Id())
oauth2, err = searchOauth2AppByClientId(client, d.Id())
if err != nil {
return err
@ -176,9 +190,10 @@ func setOAuth2ResourceData(app *gitea.Oauth2, d *schema.ResourceData) (err error
d.SetId(app.ClientID)
for k, v := range map[string]interface{}{
oauth2KeyName: app.Name,
oauth2KeyRedirectURIs: schema.NewSet(schema.HashString, CollapseStringList(app.RedirectURIs)),
oauth2KeyClientId: app.ClientID,
oauth2KeyName: app.Name,
oauth2KeyConfidentialClient: app.ConfidentialClient,
oauth2KeyRedirectURIs: schema.NewSet(schema.HashString, CollapseStringList(app.RedirectURIs)),
oauth2KeyClientId: app.ClientID,
} {
err = d.Set(k, v)
if err != nil {

View File

@ -16,6 +16,7 @@ const (
orgLocation string = "location"
orgVisibility string = "visibility"
RepoAdminChangeTeamAccess string = "repo_admin_change_team_access"
orgRepos string = "org_repos"
)
// might come in handy if we want to stick to numeric IDs
@ -48,6 +49,32 @@ func searchOrgByClientId(c *gitea.Client, id int64) (res *gitea.Organization, er
}
}
func getAllOrgRepos(c *gitea.Client, orgName string) (repos []string, err error) {
page := 1
for {
repoBuffer, _, err := c.ListOrgRepos(orgName, gitea.ListOrgReposOptions{
ListOptions: gitea.ListOptions{
Page: page,
PageSize: 50,
},
})
if err != nil {
return nil, err
}
if len(repoBuffer) == 0 {
return repos, nil
}
for _, repo := range repoBuffer {
repos = append(repos, repo.Name)
}
page += 1
}
}
func resourceOrgRead(d *schema.ResourceData, meta interface{}) (err error) {
client := meta.(*gitea.Client)
@ -58,10 +85,12 @@ func resourceOrgRead(d *schema.ResourceData, meta interface{}) (err error) {
org, err = searchOrgByClientId(client, id)
if err != nil {
return err
d.SetId("")
return nil
}
err = setOrgResourceData(org, d)
repos, _ := getAllOrgRepos(client, org.UserName)
err = setOrgResourceData(org, d, &repos)
return
}
@ -84,7 +113,8 @@ func resourceOrgCreate(d *schema.ResourceData, meta interface{}) (err error) {
return
}
err = setOrgResourceData(org, d)
repos, _ := getAllOrgRepos(client, org.UserName)
err = setOrgResourceData(org, d, &repos)
return
}
@ -117,7 +147,8 @@ func resourceOrgUpdate(d *schema.ResourceData, meta interface{}) (err error) {
org, resp, err = client.GetOrg(d.Get(orgName).(string))
err = setOrgResourceData(org, d)
repos, _ := getAllOrgRepos(client, org.UserName)
err = setOrgResourceData(org, d, &repos)
return
}
@ -140,7 +171,7 @@ func resourceOrgDelete(d *schema.ResourceData, meta interface{}) (err error) {
return
}
func setOrgResourceData(org *gitea.Organization, d *schema.ResourceData) (err error) {
func setOrgResourceData(org *gitea.Organization, d *schema.ResourceData, repos *[]string) (err error) {
d.SetId(fmt.Sprintf("%d", org.ID))
d.Set("name", org.UserName)
d.Set("full_name", org.FullName)
@ -149,6 +180,7 @@ func setOrgResourceData(org *gitea.Organization, d *schema.ResourceData) (err er
d.Set("website", org.Website)
d.Set("location", org.Location)
d.Set("visibility", org.Visibility)
d.Set("repos", repos)
return
}
@ -210,6 +242,13 @@ func resourceGiteaOrg() *schema.Resource {
Default: "public",
Description: "Flag is this organisation should be publicly visible or not.",
},
"repos": {
Type: schema.TypeList,
Required: false,
Computed: true,
Description: "List of all Repositories that are part of this organisation",
Elem: &schema.Schema{Type: schema.TypeString},
},
},
Description: "`gitea_org` manages a gitea organisation.\n\n" +
"Organisations are a way to group repositories and abstract permission management in a gitea instance.",

View File

@ -1,10 +1,14 @@
package gitea
import (
"context"
"errors"
"fmt"
"strconv"
"strings"
"code.gitea.io/sdk/gitea"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
@ -48,6 +52,34 @@ const (
migrationLFSEndpoint string = "migration_lfs_endpoint"
)
func searchUserByName(c *gitea.Client, name string) (res *gitea.User, err error) {
page := 1
for {
users, _, err := c.AdminListUsers(gitea.AdminListUsersOptions{
ListOptions: gitea.ListOptions{
Page: page,
PageSize: 50,
},
})
if err != nil {
return nil, err
}
if len(users) == 0 {
return nil, fmt.Errorf("User with name %s could not be found", name)
}
for _, user := range users {
if user.UserName == name {
return user, nil
}
}
page += 1
}
}
func resourceRepoRead(d *schema.ResourceData, meta interface{}) (err error) {
client := meta.(*gitea.Client)
@ -78,15 +110,35 @@ func resourceRepoCreate(d *schema.ResourceData, meta interface{}) (err error) {
client := meta.(*gitea.Client)
var repo *gitea.Repository
var resp *gitea.Response
var orgRepo, hasAdmin bool
if (d.Get(repoMirror)).(bool) {
_, resp, err = client.GetOrg(d.Get(repoOwner).(string))
var cloneAddr string
if d.Get(migrationCloneAddresse).(string) != "" {
cloneAddr = d.Get(migrationCloneAddresse).(string)
if resp.StatusCode == 404 {
_, err := searchUserByName(client, d.Get(repoOwner).(string))
if err != nil {
if strings.Contains(err.Error(), "could not be found") {
return errors.New(fmt.Sprintf("Creation of repository cound not proceed as owner %s is not present in gitea", d.Get(repoOwner).(string)))
}
tflog.Warn(context.Background(), "Error query for users. Assuming missing permissions and proceding with user permissions")
hasAdmin = false
} else {
cloneAddr = d.Get(migrationCloneAddress).(string)
hasAdmin = true
}
orgRepo = false
} else {
orgRepo = true
}
var cloneAddr string
if d.Get(migrationCloneAddresse).(string) != "" {
cloneAddr = d.Get(migrationCloneAddresse).(string)
} else {
cloneAddr = d.Get(migrationCloneAddress).(string)
}
if cloneAddr != "" {
opts := gitea.MigrateRepoOption{
RepoName: d.Get(repoName).(string),
@ -134,7 +186,15 @@ func resourceRepoCreate(d *schema.ResourceData, meta interface{}) (err error) {
TrustModel: "default",
}
repo, _, err = client.CreateOrgRepo(d.Get(repoOwner).(string), opts)
if orgRepo {
repo, _, err = client.CreateOrgRepo(d.Get(repoOwner).(string), opts)
} else {
if hasAdmin {
repo, _, err = client.AdminCreateRepo(d.Get(repoOwner).(string), opts)
} else {
repo, _, err = client.CreateRepo(opts)
}
}
}
if err != nil {
@ -533,6 +593,8 @@ func resourceGiteaRepository() *schema.Resource {
"Per default this repository will be initializiled with the provided configuration (gitignore, License etc.).\n" +
"If the `username` property is set to a organisation name, the provider will try to look if this organisation exists " +
"and create the repository under the organisation scope.\n\n" +
"Repository migrations have some properties that are not available to regular repositories. These are all prefixed with `migration_`.",
"Repository migrations have some properties that are not available to regular repositories. These are all prefixed with `migration_`.\n" +
"Codeberg.org does currently not allow mirrors to be created. See FAQ Section of CodeBerg for more information: " +
"https://docs.codeberg.org/getting-started/faq/#why-am-i-not-allowed-to-set-up-an-automatic-mirror",
}
}

View File

@ -0,0 +1,169 @@
package gitea
import (
"fmt"
"strconv"
"strings"
"code.gitea.io/sdk/gitea"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
const (
deployKeyRepoId string = "repository"
deployKeyName string = "title"
deployKeyKey string = "key"
deployKeyReadOnly string = "read_only"
)
func resourceRepoKeyIdParts(d *schema.ResourceData) (bool, int64, int64, error) {
parts := strings.Split(d.Id(), "/")
if len(parts) != 2 {
return false, 0, 0, nil
}
repoId, err := strconv.ParseInt(parts[0], 10, 64)
if err != nil {
return false, 0, 0, err
}
keyId, err := strconv.ParseInt(parts[1], 10, 64)
if err != nil {
return false, 0, 0, err
}
return true, repoId, keyId, err
}
func resourceRepoKeyRead(d *schema.ResourceData, meta interface{}) (err error) {
client := meta.(*gitea.Client)
hasId, repoId, keyId, err := resourceRepoKeyIdParts(d)
if err != nil {
return err
}
if !hasId {
d.SetId("")
return nil
}
repo, resp, err := client.GetRepoByID(repoId)
if err != nil {
if resp.StatusCode == 404 {
d.SetId("")
return nil
} else {
return err
}
}
key, resp, err := client.GetDeployKey(repo.Owner.UserName, repo.Name, keyId)
if err != nil {
if resp.StatusCode == 404 {
d.SetId("")
return nil
} else {
return err
}
}
err = setRepoKeyResourceData(key, repoId, d)
return
}
func resourceRepoKeyCreate(d *schema.ResourceData, meta interface{}) (err error) {
client := meta.(*gitea.Client)
repo, _, err := client.GetRepoByID(int64(d.Get(deployKeyRepoId).(int)))
if err != nil {
return err
}
dk, _, err := client.CreateDeployKey(repo.Owner.UserName, repo.Name, gitea.CreateKeyOption{
Title: d.Get(deployKeyName).(string),
ReadOnly: d.Get(deployKeyReadOnly).(bool),
Key: d.Get(deployKeyKey).(string),
})
if err != nil {
return err
}
setRepoKeyResourceData(dk, repo.ID, d)
return nil
}
func respurceRepoKeyDelete(d *schema.ResourceData, meta interface{}) (err error) {
client := meta.(*gitea.Client)
hasId, repoId, keyId, err := resourceRepoKeyIdParts(d)
if err != nil {
return err
}
if !hasId {
d.SetId("")
return nil
}
repo, resp, err := client.GetRepoByID(repoId)
if err != nil {
if resp.StatusCode == 404 {
d.SetId("")
return nil
}
return err
}
client.DeleteDeployKey(repo.Owner.UserName, repo.Name, keyId)
return nil
}
func setRepoKeyResourceData(dk *gitea.DeployKey, repoId int64, d *schema.ResourceData) (err error) {
d.SetId(fmt.Sprintf("%d/%d", repoId, dk.ID))
d.Set(deployKeyRepoId, repoId)
d.Set(deployKeyReadOnly, dk.ReadOnly)
d.Set(deployKeyKey, dk.Key)
d.Set(deployKeyName, dk.Title)
return
}
func resourceGiteaRepositoryKey() *schema.Resource {
return &schema.Resource{
Read: resourceRepoKeyRead,
Create: resourceRepoKeyCreate,
Delete: respurceRepoKeyDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Schema: map[string]*schema.Schema{
deployKeyRepoId: {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
Description: "The ID of the repository where the deploy key belongs to",
},
deployKeyKey: {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "Armored SSH key to add",
},
deployKeyReadOnly: {
Type: schema.TypeBool,
Required: false,
Optional: true,
Default: true,
ForceNew: true,
Description: "Whether this key has read or read/write access",
},
deployKeyName: {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "Name of the deploy key",
},
},
Description: "`gitea_repository_key` manages a deploy key for a single gitea_repository.\n\n" +
"Every key needs a unique name and unique key, i.e. no key can be added twice to the same repo",
}
}

View File

@ -1,6 +1,7 @@
package gitea
import (
"errors"
"fmt"
"strconv"
"strings"
@ -18,6 +19,7 @@ const (
TeamIncludeAllReposFlag string = "include_all_repositories"
TeamUnits string = "units"
TeamMembers string = "members"
TeamRepositories string = "repositories"
)
func resourceTeamRead(d *schema.ResourceData, meta interface{}) (err error) {
@ -39,7 +41,7 @@ func resourceTeamRead(d *schema.ResourceData, meta interface{}) (err error) {
}
}
err = setTeamResourceData(team, d)
err = setTeamResourceData(team, d, meta)
return
}
@ -75,12 +77,14 @@ func resourceTeamCreate(d *schema.ResourceData, meta interface{}) (err error) {
units = append(units, gitea.RepoUnitProjects)
}
includeAllRepos := d.Get(TeamIncludeAllReposFlag).(bool)
opts := gitea.CreateTeamOption{
Name: d.Get(TeamName).(string),
Description: d.Get(TeamDescription).(string),
Permission: gitea.AccessMode(d.Get(TeamPermissions).(string)),
CanCreateOrgRepo: d.Get(TeamCreateRepoFlag).(bool),
IncludesAllRepositories: d.Get(TeamIncludeAllReposFlag).(bool),
IncludesAllRepositories: includeAllRepos,
Units: units,
}
@ -101,7 +105,14 @@ func resourceTeamCreate(d *schema.ResourceData, meta interface{}) (err error) {
}
}
err = setTeamResourceData(team, d)
if !includeAllRepos {
err = setTeamRepositories(team, d, meta, false)
if err != nil {
return err
}
}
err = setTeamResourceData(team, d, meta)
return
}
@ -181,9 +192,16 @@ func resourceTeamUpdate(d *schema.ResourceData, meta interface{}) (err error) {
}
}
if !includeAllRepos {
err = setTeamRepositories(team, d, meta, true)
if err != nil {
return err
}
}
team, _, _ = client.GetTeam(id)
err = setTeamResourceData(team, d)
err = setTeamResourceData(team, d, meta)
return
}
@ -208,7 +226,13 @@ func resourceTeamDelete(d *schema.ResourceData, meta interface{}) (err error) {
return
}
func setTeamResourceData(team *gitea.Team, d *schema.ResourceData) (err error) {
func setTeamResourceData(team *gitea.Team, d *schema.ResourceData, meta interface{}) (err error) {
client := meta.(*gitea.Client)
if err := client.CheckServerVersionConstraint(">= 1.19.4"); err != nil {
d.Set(TeamOrg, d.Get(TeamOrg).(string))
} else {
d.Set(TeamOrg, team.Organization.UserName)
}
d.SetId(fmt.Sprintf("%d", team.ID))
d.Set(TeamCreateRepoFlag, team.CanCreateOrgRepo)
d.Set(TeamDescription, team.Description)
@ -216,8 +240,8 @@ func setTeamResourceData(team *gitea.Team, d *schema.ResourceData) (err error) {
d.Set(TeamPermissions, string(team.Permission))
d.Set(TeamIncludeAllReposFlag, team.IncludesAllRepositories)
d.Set(TeamUnits, d.Get(TeamUnits).(string))
d.Set(TeamOrg, d.Get(TeamOrg).(string))
d.Set(TeamMembers, d.Get(TeamMembers))
d.Set(TeamRepositories, d.Get(TeamRepositories))
return
}
@ -228,7 +252,7 @@ func resourceGiteaTeam() *schema.Resource {
Update: resourceTeamUpdate,
Delete: resourceTeamDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
StateContext: schema.ImportStatePassthroughContext,
},
Schema: map[string]*schema.Schema{
"name": {
@ -290,7 +314,75 @@ func resourceGiteaTeam() *schema.Resource {
Computed: true,
Description: "List of Users that should be part of this team",
},
"repositories": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Optional: true,
Required: false,
Computed: true,
Description: "List of Repositories that should be part of this team",
},
},
Description: "`gitea_team` manages Team that are part of an organisation.",
}
}
func setTeamRepositories(team *gitea.Team, d *schema.ResourceData, meta interface{}, update bool) (err error) {
client := meta.(*gitea.Client)
org := d.Get(TeamOrg).(string)
repositories := make(map[string]bool)
for _, repo := range d.Get(TeamRepositories).([]interface{}) {
if repo != "" {
repositories[repo.(string)] = true
}
}
if update {
page := 1
for {
var existingRepositories []*gitea.Repository
existingRepositories, _, err = client.ListTeamRepositories(team.ID, gitea.ListTeamRepositoriesOptions{
ListOptions: gitea.ListOptions{
Page: page,
PageSize: 50,
},
})
if err != nil {
return errors.New(fmt.Sprintf("[ERROR] Error listeng team repositories: %s", err))
}
if len(existingRepositories) == 0 {
break
}
for _, exr := range existingRepositories {
_, exists := repositories[exr.Name]
if exists {
repositories[exr.Name] = false
} else {
_, err = client.RemoveTeamRepository(team.ID, org, exr.Name)
if err != nil {
return errors.New(fmt.Sprintf("[ERROR] Error removing team repository %q: %s", exr.Name, err))
}
}
}
page += 1
}
}
for repo, flag := range repositories {
if flag {
_, err = client.AddTeamRepository(team.ID, org, repo)
if err != nil {
return errors.New(fmt.Sprintf("[ERROR] Error adding team repository %q: %s", repo, err))
}
}
}
return
}

79
go.mod
View File

@ -4,65 +4,70 @@ go 1.18
require (
code.gitea.io/sdk/gitea v0.15.1
github.com/hashicorp/terraform-plugin-docs v0.7.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0
github.com/hashicorp/terraform-plugin-docs v0.16.0
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.27.0
)
require (
github.com/Masterminds/goutils v1.1.0 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.2 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect
github.com/agext/levenshtein v1.2.2 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
github.com/hashicorp/go-hclog v1.2.1 // indirect
github.com/hashicorp/go-hclog v1.5.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-plugin v1.4.4 // indirect
github.com/hashicorp/go-plugin v1.4.10 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/hc-install v0.4.0 // indirect
github.com/hashicorp/hcl/v2 v2.13.0 // indirect
github.com/hashicorp/hc-install v0.5.2 // indirect
github.com/hashicorp/hcl/v2 v2.17.0 // indirect
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/terraform-exec v0.17.2 // indirect
github.com/hashicorp/terraform-json v0.14.0 // indirect
github.com/hashicorp/terraform-plugin-go v0.12.0 // indirect
github.com/hashicorp/terraform-plugin-log v0.7.0 // indirect
github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c // indirect
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect
github.com/hashicorp/terraform-exec v0.18.1 // indirect
github.com/hashicorp/terraform-json v0.17.1 // indirect
github.com/hashicorp/terraform-plugin-go v0.16.0 // indirect
github.com/hashicorp/terraform-registry-address v0.2.1 // indirect
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mitchellh/cli v1.1.2 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mitchellh/cli v1.1.5 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/oklog/run v1.0.0 // indirect
github.com/posener/complete v1.1.1 // indirect
github.com/posener/complete v1.2.3 // indirect
github.com/russross/blackfriday v1.6.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
github.com/vmihailenco/tagparser v0.1.1 // indirect
github.com/zclconf/go-cty v1.10.0 // indirect
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167 // indirect
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/appengine v1.6.6 // indirect
google.golang.org/genproto v0.0.0-20200711021454-869866162049 // indirect
google.golang.org/grpc v1.48.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/zclconf/go-cty v1.13.2 // indirect
golang.org/x/crypto v0.10.0 // indirect
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect
golang.org/x/mod v0.11.0 // indirect
golang.org/x/net v0.11.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/text v0.11.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/grpc v1.56.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
)

346
go.sum
View File

@ -1,189 +1,133 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
code.gitea.io/gitea-vet v0.2.1/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
code.gitea.io/sdk/gitea v0.15.1 h1:WJreC7YYuxbn0UDaPuWIe/mtiNKTvLN8MLkaw71yx/M=
code.gitea.io/sdk/gitea v0.15.1/go.mod h1:klY2LVI3s3NChzIk/MzMn7G1FHrfU7qd63iSMVoHRBA=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE=
github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I=
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
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/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34=
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4=
github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU=
github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI=
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs=
github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw=
github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-plugin v1.4.4 h1:NVdrSdFRt3SkZtNckJ6tog7gbpRrcbOjQi/rgF7JYWQ=
github.com/hashicorp/go-plugin v1.4.4/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
github.com/hashicorp/go-plugin v1.4.10 h1:xUbmA4jC6Dq163/fWcp8P3JuHilrHHMLNRxzGQJ9hNk=
github.com/hashicorp/go-plugin v1.4.10/go.mod h1:6/1TEzT0eQznvI/gV2CM29DLSkAK/e58mUWKVsPaph0=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/hc-install v0.4.0 h1:cZkRFr1WVa0Ty6x5fTvL1TuO1flul231rWkGH92oYYk=
github.com/hashicorp/hc-install v0.4.0/go.mod h1:5d155H8EC5ewegao9A4PUTMNPZaq+TbOzkJJZ4vrXeI=
github.com/hashicorp/hcl/v2 v2.13.0 h1:0Apadu1w6M11dyGFxWnmhhcMjkbAiKCv7G1r/2QgCNc=
github.com/hashicorp/hcl/v2 v2.13.0/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0=
github.com/hashicorp/hc-install v0.5.2 h1:SfwMFnEXVVirpwkDuSF5kymUOhrUxrTq3udEseZdOD0=
github.com/hashicorp/hc-install v0.5.2/go.mod h1:9QISwe6newMWIfEiXpzuu1k9HAGtQYgnSH8H9T8wmoI=
github.com/hashicorp/hcl/v2 v2.17.0 h1:z1XvSUyXd1HP10U4lrLg5e0JMVz6CPaJvAgxM0KNZVY=
github.com/hashicorp/hcl/v2 v2.17.0/go.mod h1:gJyW2PTShkJqQBKpAmPO3yxMxIuoXkOF2TpqXzrQyx4=
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/terraform-exec v0.17.2 h1:EU7i3Fh7vDUI9nNRdMATCEfnm9axzTnad8zszYZ73Go=
github.com/hashicorp/terraform-exec v0.17.2/go.mod h1:tuIbsL2l4MlwwIZx9HPM+LOV9vVyEfBYu2GsO1uH3/8=
github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s=
github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM=
github.com/hashicorp/terraform-plugin-docs v0.7.0 h1:7XKAOYHAxghe7q4/vx468X43X9GikdQ2dxtmcu2gQv0=
github.com/hashicorp/terraform-plugin-docs v0.7.0/go.mod h1:57CICKfW7/KbW4lPhKOledyT6vu1LeAOzuvWXsVaxUE=
github.com/hashicorp/terraform-plugin-go v0.12.0 h1:6wW9mT1dSs0Xq4LR6HXj1heQ5ovr5GxXNJwkErZzpJw=
github.com/hashicorp/terraform-plugin-go v0.12.0/go.mod h1:kwhmaWHNDvT1B3QiSJdAtrB/D4RaKSY/v3r2BuoWK4M=
github.com/hashicorp/terraform-plugin-log v0.7.0 h1:SDxJUyT8TwN4l5b5/VkiTIaQgY6R+Y2BQ0sRZftGKQs=
github.com/hashicorp/terraform-plugin-log v0.7.0/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0 h1:+KxZULPsbjpAVoP0WNj/8aVW6EqpcX5JcUcQ5wl7Da4=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0/go.mod h1:DwGJG3KNxIPluVk6hexvDfYR/MS/eKGpiztJoT3Bbbw=
github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c h1:D8aRO6+mTqHfLsK/BC3j5OAoogv1WLRWzY1AaTo3rBg=
github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c/go.mod h1:Wn3Na71knbXc1G8Lh+yu/dQWWJeFQEpDeJMtWMtlmNI=
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 h1:HKLsbzeOsfXmKNpr3GiT18XAblV0BjCbzL8KQAMZGa0=
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg=
github.com/hashicorp/terraform-exec v0.18.1 h1:LAbfDvNQU1l0NOQlTuudjczVhHj061fNX5H8XZxHlH4=
github.com/hashicorp/terraform-exec v0.18.1/go.mod h1:58wg4IeuAJ6LVsLUeD2DWZZoc/bYi6dzhLHzxM41980=
github.com/hashicorp/terraform-json v0.17.1 h1:eMfvh/uWggKmY7Pmb3T85u86E2EQg6EQHgyRwf3RkyA=
github.com/hashicorp/terraform-json v0.17.1/go.mod h1:Huy6zt6euxaY9knPAFKjUITn8QxUFIe9VuSzb4zn/0o=
github.com/hashicorp/terraform-plugin-docs v0.16.0 h1:UmxFr3AScl6Wged84jndJIfFccGyBZn52KtMNsS12dI=
github.com/hashicorp/terraform-plugin-docs v0.16.0/go.mod h1:M3ZrlKBJAbPMtNOPwHicGi1c+hZUh7/g0ifT/z7TVfA=
github.com/hashicorp/terraform-plugin-go v0.16.0 h1:DSOQ0rz5FUiVO4NUzMs8ln9gsPgHMTsfns7Nk+6gPuE=
github.com/hashicorp/terraform-plugin-go v0.16.0/go.mod h1:4sn8bFuDbt+2+Yztt35IbOrvZc0zyEi87gJzsTgCES8=
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.27.0 h1:I8efBnjuDrgPjNF1MEypHy48VgcTIUY4X6rOFunrR3Y=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.27.0/go.mod h1:cUEP4ly/nxlHy5HzD6YRrHydtlheGvGRJDhiWqqVik4=
github.com/hashicorp/terraform-registry-address v0.2.1 h1:QuTf6oJ1+WSflJw6WYOHhLgwUiQ0FrROpHPYFtwTYWM=
github.com/hashicorp/terraform-registry-address v0.2.1/go.mod h1:BSE9fIFzp0qWsJUUyGquo4ldV9k2n+psif6NYkBRS3Y=
github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ=
github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
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/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
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/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw=
github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mitchellh/cli v1.1.5 h1:OxRIeJXpAMztws/XHlN2vu6imG5Dpq+j61AzAX5fLng=
github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
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/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
@ -193,180 +137,108 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758=
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
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/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U=
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
github.com/zclconf/go-cty v1.10.0 h1:mp9ZXQeIcN8kAwuqorjH+Q+njbJKjLrvB2yIh4q7U+0=
github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
github.com/zclconf/go-cty v1.13.2 h1:4GvrUxe/QUDYuJKAav4EYqdM47/kZa672LwmXFmEKT0=
github.com/zclconf/go-cty v1.13.2/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167 h1:O8uGbHCqlTp2P6QJSLmCojM4mN6UemYv8K+dCnmHmu0=
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200711021454-869866162049 h1:YFTFpQhgvrLrmxtiIncJxFXeCyq84ixuKWVCaCAi9Oc=
google.golang.org/genproto v0.0.0-20200711021454-869866162049/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w=
google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
google.golang.org/grpc v1.56.0 h1:+y7Bs8rtMd07LeXmL3NxcTLn7mUkbKZqEpPhMNkwJEE=
google.golang.org/grpc v1.56.0/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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-20200227125254-8fa46927fb4f/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=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -6,7 +6,7 @@ networks:
services:
server:
image: gitea/gitea:1.17.1
image: gitea/gitea:1.19.3
container_name: gitea
environment:
- USER_UID=1000

View File

@ -13,12 +13,13 @@ import (
// Oauth2 represents an Oauth2 Application
type Oauth2 struct {
ID int64 `json:"id"`
Name string `json:"name"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
RedirectURIs []string `json:"redirect_uris"`
Created time.Time `json:"created"`
ID int64 `json:"id"`
Name string `json:"name"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
RedirectURIs []string `json:"redirect_uris"`
ConfidentialClient bool `json:"confidential_client"`
Created time.Time `json:"created"`
}
// ListOauth2Option for listing Oauth2 Applications
@ -28,8 +29,9 @@ type ListOauth2Option struct {
// CreateOauth2Option required options for creating an Application
type CreateOauth2Option struct {
Name string `json:"name"`
RedirectURIs []string `json:"redirect_uris"`
Name string `json:"name"`
ConfidentialClient bool `json:"confidential_client"`
RedirectURIs []string `json:"redirect_uris"`
}
// CreateOauth2 create an Oauth2 Application and returns a completed Oauth2 object.

View File

@ -21,7 +21,6 @@ import (
"fmt"
"math"
"math/big"
"regexp"
"unicode"
)
@ -99,27 +98,7 @@ Returns:
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
*/
func CryptoRandomAlphaNumeric(count int) (string, error) {
if count == 0 {
return "", nil
}
RandomString, err := CryptoRandom(count, 0, 0, true, true)
if err != nil {
return "", fmt.Errorf("Error: %s", err)
}
match, err := regexp.MatchString("([0-9]+)", RandomString)
if err != nil {
panic(err)
}
if !match {
//Get the position between 0 and the length of the string-1 to insert a random number
position := getCryptoRandomInt(count)
//Insert a random number between [0-9] in the position
RandomString = RandomString[:position] + string('0' + getCryptoRandomInt(10)) + RandomString[position + 1:]
return RandomString, err
}
return RandomString, err
return CryptoRandom(count, 0, 0, true, true)
}
/*
@ -204,7 +183,7 @@ func CryptoRandom(count int, start int, end int, letters bool, numbers bool, cha
if chars == nil {
ch = rune(getCryptoRandomInt(gap) + int64(start))
} else {
ch = chars[getCryptoRandomInt(gap) + int64(start)]
ch = chars[getCryptoRandomInt(gap)+int64(start)]
}
if letters && unicode.IsLetter(ch) || numbers && unicode.IsDigit(ch) || !letters && !numbers {

View File

@ -20,7 +20,6 @@ import (
"fmt"
"math"
"math/rand"
"regexp"
"time"
"unicode"
)
@ -75,12 +74,10 @@ func RandomNumeric(count int) (string, error) {
/*
RandomAlphabetic creates a random string whose length is the number of characters specified.
Characters will be chosen from the set of alpha-numeric characters as indicated by the arguments.
Characters will be chosen from the set of alphabetic characters.
Parameters:
count - the length of random string to create
letters - if true, generated string may include alphabetic characters
numbers - if true, generated string may include numeric characters
Returns:
string - the random string
@ -102,24 +99,7 @@ Returns:
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
*/
func RandomAlphaNumeric(count int) (string, error) {
RandomString, err := Random(count, 0, 0, true, true)
if err != nil {
return "", fmt.Errorf("Error: %s", err)
}
match, err := regexp.MatchString("([0-9]+)", RandomString)
if err != nil {
panic(err)
}
if !match {
//Get the position between 0 and the length of the string-1 to insert a random number
position := rand.Intn(count)
//Insert a random number between [0-9] in the position
RandomString = RandomString[:position] + string('0'+rand.Intn(10)) + RandomString[position+1:]
return RandomString, err
}
return RandomString, err
return Random(count, 0, 0, true, true)
}
/*

View File

@ -222,3 +222,19 @@ func IndexOf(str string, sub string, start int) int {
func IsEmpty(str string) bool {
return len(str) == 0
}
// Returns either the passed in string, or if the string is empty, the value of defaultStr.
func DefaultString(str string, defaultStr string) string {
if IsEmpty(str) {
return defaultStr
}
return str
}
// Returns either the passed in string, or if the string is whitespace, empty (""), the value of defaultStr.
func DefaultIfBlank(str string, defaultStr string) string {
if IsBlank(str) {
return defaultStr
}
return str
}

View File

@ -1,29 +0,0 @@
language: go
go:
- 1.6.x
- 1.7.x
- 1.8.x
- 1.9.x
- 1.10.x
- 1.11.x
- 1.12.x
- tip
# Setting sudo access to false will let Travis CI use containers rather than
# VMs to run the tests. For more details see:
# - http://docs.travis-ci.com/user/workers/container-based-infrastructure/
# - http://docs.travis-ci.com/user/workers/standard-infrastructure/
sudo: false
script:
- make setup
- make test
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/06e3328629952dabe3e0
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: never # options: [always|never|change] default: always

View File

@ -1,109 +0,0 @@
# 1.5.0 (2019-09-11)
## Added
- #103: Add basic fuzzing for `NewVersion()` (thanks @jesse-c)
## Changed
- #82: Clarify wildcard meaning in range constraints and update tests for it (thanks @greysteil)
- #83: Clarify caret operator range for pre-1.0.0 dependencies (thanks @greysteil)
- #72: Adding docs comment pointing to vert for a cli
- #71: Update the docs on pre-release comparator handling
- #89: Test with new go versions (thanks @thedevsaddam)
- #87: Added $ to ValidPrerelease for better validation (thanks @jeremycarroll)
## Fixed
- #78: Fix unchecked error in example code (thanks @ravron)
- #70: Fix the handling of pre-releases and the 0.0.0 release edge case
- #97: Fixed copyright file for proper display on GitHub
- #107: Fix handling prerelease when sorting alphanum and num
- #109: Fixed where Validate sometimes returns wrong message on error
# 1.4.2 (2018-04-10)
## Changed
- #72: Updated the docs to point to vert for a console appliaction
- #71: Update the docs on pre-release comparator handling
## Fixed
- #70: Fix the handling of pre-releases and the 0.0.0 release edge case
# 1.4.1 (2018-04-02)
## Fixed
- Fixed #64: Fix pre-release precedence issue (thanks @uudashr)
# 1.4.0 (2017-10-04)
## Changed
- #61: Update NewVersion to parse ints with a 64bit int size (thanks @zknill)
# 1.3.1 (2017-07-10)
## Fixed
- Fixed #57: number comparisons in prerelease sometimes inaccurate
# 1.3.0 (2017-05-02)
## Added
- #45: Added json (un)marshaling support (thanks @mh-cbon)
- Stability marker. See https://masterminds.github.io/stability/
## Fixed
- #51: Fix handling of single digit tilde constraint (thanks @dgodd)
## Changed
- #55: The godoc icon moved from png to svg
# 1.2.3 (2017-04-03)
## Fixed
- #46: Fixed 0.x.x and 0.0.x in constraints being treated as *
# Release 1.2.2 (2016-12-13)
## Fixed
- #34: Fixed issue where hyphen range was not working with pre-release parsing.
# Release 1.2.1 (2016-11-28)
## Fixed
- #24: Fixed edge case issue where constraint "> 0" does not handle "0.0.1-alpha"
properly.
# Release 1.2.0 (2016-11-04)
## Added
- #20: Added MustParse function for versions (thanks @adamreese)
- #15: Added increment methods on versions (thanks @mh-cbon)
## Fixed
- Issue #21: Per the SemVer spec (section 9) a pre-release is unstable and
might not satisfy the intended compatibility. The change here ignores pre-releases
on constraint checks (e.g., ~ or ^) when a pre-release is not part of the
constraint. For example, `^1.2.3` will ignore pre-releases while
`^1.2.3-alpha` will include them.
# Release 1.1.1 (2016-06-30)
## Changed
- Issue #9: Speed up version comparison performance (thanks @sdboyer)
- Issue #8: Added benchmarks (thanks @sdboyer)
- Updated Go Report Card URL to new location
- Updated Readme to add code snippet formatting (thanks @mh-cbon)
- Updating tagging to v[SemVer] structure for compatibility with other tools.
# Release 1.1.0 (2016-03-11)
- Issue #2: Implemented validation to provide reasons a versions failed a
constraint.
# Release 1.0.1 (2015-12-31)
- Fixed #1: * constraint failing on valid versions.
# Release 1.0.0 (2015-10-20)
- Initial release

View File

@ -1,36 +0,0 @@
.PHONY: setup
setup:
go get -u gopkg.in/alecthomas/gometalinter.v1
gometalinter.v1 --install
.PHONY: test
test: validate lint
@echo "==> Running tests"
go test -v
.PHONY: validate
validate:
@echo "==> Running static validations"
@gometalinter.v1 \
--disable-all \
--enable deadcode \
--severity deadcode:error \
--enable gofmt \
--enable gosimple \
--enable ineffassign \
--enable misspell \
--enable vet \
--tests \
--vendor \
--deadline 60s \
./... || exit_code=1
.PHONY: lint
lint:
@echo "==> Running linters"
@gometalinter.v1 \
--disable-all \
--enable golint \
--vendor \
--deadline 60s \
./... || :

View File

@ -1,194 +0,0 @@
# SemVer
The `semver` package provides the ability to work with [Semantic Versions](http://semver.org) in Go. Specifically it provides the ability to:
* Parse semantic versions
* Sort semantic versions
* Check if a semantic version fits within a set of constraints
* Optionally work with a `v` prefix
[![Stability:
Active](https://masterminds.github.io/stability/active.svg)](https://masterminds.github.io/stability/active.html)
[![Build Status](https://travis-ci.org/Masterminds/semver.svg)](https://travis-ci.org/Masterminds/semver) [![Build status](https://ci.appveyor.com/api/projects/status/jfk66lib7hb985k8/branch/master?svg=true&passingText=windows%20build%20passing&failingText=windows%20build%20failing)](https://ci.appveyor.com/project/mattfarina/semver/branch/master) [![GoDoc](https://godoc.org/github.com/Masterminds/semver?status.svg)](https://godoc.org/github.com/Masterminds/semver) [![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/semver)](https://goreportcard.com/report/github.com/Masterminds/semver)
If you are looking for a command line tool for version comparisons please see
[vert](https://github.com/Masterminds/vert) which uses this library.
## Parsing Semantic Versions
To parse a semantic version use the `NewVersion` function. For example,
```go
v, err := semver.NewVersion("1.2.3-beta.1+build345")
```
If there is an error the version wasn't parseable. The version object has methods
to get the parts of the version, compare it to other versions, convert the
version back into a string, and get the original string. For more details
please see the [documentation](https://godoc.org/github.com/Masterminds/semver).
## Sorting Semantic Versions
A set of versions can be sorted using the [`sort`](https://golang.org/pkg/sort/)
package from the standard library. For example,
```go
raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
vs := make([]*semver.Version, len(raw))
for i, r := range raw {
v, err := semver.NewVersion(r)
if err != nil {
t.Errorf("Error parsing version: %s", err)
}
vs[i] = v
}
sort.Sort(semver.Collection(vs))
```
## Checking Version Constraints
Checking a version against version constraints is one of the most featureful
parts of the package.
```go
c, err := semver.NewConstraint(">= 1.2.3")
if err != nil {
// Handle constraint not being parseable.
}
v, _ := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parseable.
}
// Check if the version meets the constraints. The a variable will be true.
a := c.Check(v)
```
## Basic Comparisons
There are two elements to the comparisons. First, a comparison string is a list
of comma separated and comparisons. These are then separated by || separated or
comparisons. For example, `">= 1.2, < 3.0.0 || >= 4.2.3"` is looking for a
comparison that's greater than or equal to 1.2 and less than 3.0.0 or is
greater than or equal to 4.2.3.
The basic comparisons are:
* `=`: equal (aliased to no operator)
* `!=`: not equal
* `>`: greater than
* `<`: less than
* `>=`: greater than or equal to
* `<=`: less than or equal to
## Working With Pre-release Versions
Pre-releases, for those not familiar with them, are used for software releases
prior to stable or generally available releases. Examples of pre-releases include
development, alpha, beta, and release candidate releases. A pre-release may be
a version such as `1.2.3-beta.1` while the stable release would be `1.2.3`. In the
order of precidence, pre-releases come before their associated releases. In this
example `1.2.3-beta.1 < 1.2.3`.
According to the Semantic Version specification pre-releases may not be
API compliant with their release counterpart. It says,
> A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version.
SemVer comparisons without a pre-release comparator will skip pre-release versions.
For example, `>=1.2.3` will skip pre-releases when looking at a list of releases
while `>=1.2.3-0` will evaluate and find pre-releases.
The reason for the `0` as a pre-release version in the example comparison is
because pre-releases can only contain ASCII alphanumerics and hyphens (along with
`.` separators), per the spec. Sorting happens in ASCII sort order, again per the spec. The lowest character is a `0` in ASCII sort order (see an [ASCII Table](http://www.asciitable.com/))
Understanding ASCII sort ordering is important because A-Z comes before a-z. That
means `>=1.2.3-BETA` will return `1.2.3-alpha`. What you might expect from case
sensitivity doesn't apply here. This is due to ASCII sort ordering which is what
the spec specifies.
## Hyphen Range Comparisons
There are multiple methods to handle ranges and the first is hyphens ranges.
These look like:
* `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5`
* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4, <= 4.5`
## Wildcards In Comparisons
The `x`, `X`, and `*` characters can be used as a wildcard character. This works
for all comparison operators. When used on the `=` operator it falls
back to the pack level comparison (see tilde below). For example,
* `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
* `>= 1.2.x` is equivalent to `>= 1.2.0`
* `<= 2.x` is equivalent to `< 3`
* `*` is equivalent to `>= 0.0.0`
## Tilde Range Comparisons (Patch)
The tilde (`~`) comparison operator is for patch level ranges when a minor
version is specified and major level changes when the minor number is missing.
For example,
* `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0`
* `~1` is equivalent to `>= 1, < 2`
* `~2.3` is equivalent to `>= 2.3, < 2.4`
* `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
* `~1.x` is equivalent to `>= 1, < 2`
## Caret Range Comparisons (Major)
The caret (`^`) comparison operator is for major level changes. This is useful
when comparisons of API versions as a major change is API breaking. For example,
* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0`
* `^0.0.1` is equivalent to `>= 0.0.1, < 1.0.0`
* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0`
* `^2.3` is equivalent to `>= 2.3, < 3`
* `^2.x` is equivalent to `>= 2.0.0, < 3`
# Validation
In addition to testing a version against a constraint, a version can be validated
against a constraint. When validation fails a slice of errors containing why a
version didn't meet the constraint is returned. For example,
```go
c, err := semver.NewConstraint("<= 1.2.3, >= 1.4")
if err != nil {
// Handle constraint not being parseable.
}
v, _ := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parseable.
}
// Validate a version against a constraint.
a, msgs := c.Validate(v)
// a is false
for _, m := range msgs {
fmt.Println(m)
// Loops over the errors which would read
// "1.3 is greater than 1.2.3"
// "1.3 is less than 1.4"
}
```
# Fuzzing
[dvyukov/go-fuzz](https://github.com/dvyukov/go-fuzz) is used for fuzzing.
1. `go-fuzz-build`
2. `go-fuzz -workdir=fuzz`
# Contribute
If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues)
or [create a pull request](https://github.com/Masterminds/semver/pulls).

View File

@ -1,44 +0,0 @@
version: build-{build}.{branch}
clone_folder: C:\gopath\src\github.com\Masterminds\semver
shallow_clone: true
environment:
GOPATH: C:\gopath
platform:
- x64
install:
- go version
- go env
- go get -u gopkg.in/alecthomas/gometalinter.v1
- set PATH=%PATH%;%GOPATH%\bin
- gometalinter.v1.exe --install
build_script:
- go install -v ./...
test_script:
- "gometalinter.v1 \
--disable-all \
--enable deadcode \
--severity deadcode:error \
--enable gofmt \
--enable gosimple \
--enable ineffassign \
--enable misspell \
--enable vet \
--tests \
--vendor \
--deadline 60s \
./... || exit_code=1"
- "gometalinter.v1 \
--disable-all \
--enable golint \
--vendor \
--deadline 60s \
./... || :"
- go test -v
deploy: off

View File

@ -1,423 +0,0 @@
package semver
import (
"errors"
"fmt"
"regexp"
"strings"
)
// Constraints is one or more constraint that a semantic version can be
// checked against.
type Constraints struct {
constraints [][]*constraint
}
// NewConstraint returns a Constraints instance that a Version instance can
// be checked against. If there is a parse error it will be returned.
func NewConstraint(c string) (*Constraints, error) {
// Rewrite - ranges into a comparison operation.
c = rewriteRange(c)
ors := strings.Split(c, "||")
or := make([][]*constraint, len(ors))
for k, v := range ors {
cs := strings.Split(v, ",")
result := make([]*constraint, len(cs))
for i, s := range cs {
pc, err := parseConstraint(s)
if err != nil {
return nil, err
}
result[i] = pc
}
or[k] = result
}
o := &Constraints{constraints: or}
return o, nil
}
// Check tests if a version satisfies the constraints.
func (cs Constraints) Check(v *Version) bool {
// loop over the ORs and check the inner ANDs
for _, o := range cs.constraints {
joy := true
for _, c := range o {
if !c.check(v) {
joy = false
break
}
}
if joy {
return true
}
}
return false
}
// Validate checks if a version satisfies a constraint. If not a slice of
// reasons for the failure are returned in addition to a bool.
func (cs Constraints) Validate(v *Version) (bool, []error) {
// loop over the ORs and check the inner ANDs
var e []error
// Capture the prerelease message only once. When it happens the first time
// this var is marked
var prerelesase bool
for _, o := range cs.constraints {
joy := true
for _, c := range o {
// Before running the check handle the case there the version is
// a prerelease and the check is not searching for prereleases.
if c.con.pre == "" && v.pre != "" {
if !prerelesase {
em := fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
e = append(e, em)
prerelesase = true
}
joy = false
} else {
if !c.check(v) {
em := fmt.Errorf(c.msg, v, c.orig)
e = append(e, em)
joy = false
}
}
}
if joy {
return true, []error{}
}
}
return false, e
}
var constraintOps map[string]cfunc
var constraintMsg map[string]string
var constraintRegex *regexp.Regexp
func init() {
constraintOps = map[string]cfunc{
"": constraintTildeOrEqual,
"=": constraintTildeOrEqual,
"!=": constraintNotEqual,
">": constraintGreaterThan,
"<": constraintLessThan,
">=": constraintGreaterThanEqual,
"=>": constraintGreaterThanEqual,
"<=": constraintLessThanEqual,
"=<": constraintLessThanEqual,
"~": constraintTilde,
"~>": constraintTilde,
"^": constraintCaret,
}
constraintMsg = map[string]string{
"": "%s is not equal to %s",
"=": "%s is not equal to %s",
"!=": "%s is equal to %s",
">": "%s is less than or equal to %s",
"<": "%s is greater than or equal to %s",
">=": "%s is less than %s",
"=>": "%s is less than %s",
"<=": "%s is greater than %s",
"=<": "%s is greater than %s",
"~": "%s does not have same major and minor version as %s",
"~>": "%s does not have same major and minor version as %s",
"^": "%s does not have same major version as %s",
}
ops := make([]string, 0, len(constraintOps))
for k := range constraintOps {
ops = append(ops, regexp.QuoteMeta(k))
}
constraintRegex = regexp.MustCompile(fmt.Sprintf(
`^\s*(%s)\s*(%s)\s*$`,
strings.Join(ops, "|"),
cvRegex))
constraintRangeRegex = regexp.MustCompile(fmt.Sprintf(
`\s*(%s)\s+-\s+(%s)\s*`,
cvRegex, cvRegex))
}
// An individual constraint
type constraint struct {
// The callback function for the restraint. It performs the logic for
// the constraint.
function cfunc
msg string
// The version used in the constraint check. For example, if a constraint
// is '<= 2.0.0' the con a version instance representing 2.0.0.
con *Version
// The original parsed version (e.g., 4.x from != 4.x)
orig string
// When an x is used as part of the version (e.g., 1.x)
minorDirty bool
dirty bool
patchDirty bool
}
// Check if a version meets the constraint
func (c *constraint) check(v *Version) bool {
return c.function(v, c)
}
type cfunc func(v *Version, c *constraint) bool
func parseConstraint(c string) (*constraint, error) {
m := constraintRegex.FindStringSubmatch(c)
if m == nil {
return nil, fmt.Errorf("improper constraint: %s", c)
}
ver := m[2]
orig := ver
minorDirty := false
patchDirty := false
dirty := false
if isX(m[3]) {
ver = "0.0.0"
dirty = true
} else if isX(strings.TrimPrefix(m[4], ".")) || m[4] == "" {
minorDirty = true
dirty = true
ver = fmt.Sprintf("%s.0.0%s", m[3], m[6])
} else if isX(strings.TrimPrefix(m[5], ".")) {
dirty = true
patchDirty = true
ver = fmt.Sprintf("%s%s.0%s", m[3], m[4], m[6])
}
con, err := NewVersion(ver)
if err != nil {
// The constraintRegex should catch any regex parsing errors. So,
// we should never get here.
return nil, errors.New("constraint Parser Error")
}
cs := &constraint{
function: constraintOps[m[1]],
msg: constraintMsg[m[1]],
con: con,
orig: orig,
minorDirty: minorDirty,
patchDirty: patchDirty,
dirty: dirty,
}
return cs, nil
}
// Constraint functions
func constraintNotEqual(v *Version, c *constraint) bool {
if c.dirty {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false
}
if c.con.Major() != v.Major() {
return true
}
if c.con.Minor() != v.Minor() && !c.minorDirty {
return true
} else if c.minorDirty {
return false
}
return false
}
return !v.Equal(c.con)
}
func constraintGreaterThan(v *Version, c *constraint) bool {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false
}
return v.Compare(c.con) == 1
}
func constraintLessThan(v *Version, c *constraint) bool {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false
}
if !c.dirty {
return v.Compare(c.con) < 0
}
if v.Major() > c.con.Major() {
return false
} else if v.Minor() > c.con.Minor() && !c.minorDirty {
return false
}
return true
}
func constraintGreaterThanEqual(v *Version, c *constraint) bool {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false
}
return v.Compare(c.con) >= 0
}
func constraintLessThanEqual(v *Version, c *constraint) bool {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false
}
if !c.dirty {
return v.Compare(c.con) <= 0
}
if v.Major() > c.con.Major() {
return false
} else if v.Minor() > c.con.Minor() && !c.minorDirty {
return false
}
return true
}
// ~*, ~>* --> >= 0.0.0 (any)
// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0, <3.0.0
// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0, <2.1.0
// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0, <1.3.0
// ~1.2.3, ~>1.2.3 --> >=1.2.3, <1.3.0
// ~1.2.0, ~>1.2.0 --> >=1.2.0, <1.3.0
func constraintTilde(v *Version, c *constraint) bool {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false
}
if v.LessThan(c.con) {
return false
}
// ~0.0.0 is a special case where all constraints are accepted. It's
// equivalent to >= 0.0.0.
if c.con.Major() == 0 && c.con.Minor() == 0 && c.con.Patch() == 0 &&
!c.minorDirty && !c.patchDirty {
return true
}
if v.Major() != c.con.Major() {
return false
}
if v.Minor() != c.con.Minor() && !c.minorDirty {
return false
}
return true
}
// When there is a .x (dirty) status it automatically opts in to ~. Otherwise
// it's a straight =
func constraintTildeOrEqual(v *Version, c *constraint) bool {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false
}
if c.dirty {
c.msg = constraintMsg["~"]
return constraintTilde(v, c)
}
return v.Equal(c.con)
}
// ^* --> (any)
// ^2, ^2.x, ^2.x.x --> >=2.0.0, <3.0.0
// ^2.0, ^2.0.x --> >=2.0.0, <3.0.0
// ^1.2, ^1.2.x --> >=1.2.0, <2.0.0
// ^1.2.3 --> >=1.2.3, <2.0.0
// ^1.2.0 --> >=1.2.0, <2.0.0
func constraintCaret(v *Version, c *constraint) bool {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false
}
if v.LessThan(c.con) {
return false
}
if v.Major() != c.con.Major() {
return false
}
return true
}
var constraintRangeRegex *regexp.Regexp
const cvRegex string = `v?([0-9|x|X|\*]+)(\.[0-9|x|X|\*]+)?(\.[0-9|x|X|\*]+)?` +
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
func isX(x string) bool {
switch x {
case "x", "*", "X":
return true
default:
return false
}
}
func rewriteRange(i string) string {
m := constraintRangeRegex.FindAllStringSubmatch(i, -1)
if m == nil {
return i
}
o := i
for _, v := range m {
t := fmt.Sprintf(">= %s, <= %s", v[1], v[11])
o = strings.Replace(o, v[0], t, 1)
}
return o
}

View File

@ -1,115 +0,0 @@
/*
Package semver provides the ability to work with Semantic Versions (http://semver.org) in Go.
Specifically it provides the ability to:
* Parse semantic versions
* Sort semantic versions
* Check if a semantic version fits within a set of constraints
* Optionally work with a `v` prefix
Parsing Semantic Versions
To parse a semantic version use the `NewVersion` function. For example,
v, err := semver.NewVersion("1.2.3-beta.1+build345")
If there is an error the version wasn't parseable. The version object has methods
to get the parts of the version, compare it to other versions, convert the
version back into a string, and get the original string. For more details
please see the documentation at https://godoc.org/github.com/Masterminds/semver.
Sorting Semantic Versions
A set of versions can be sorted using the `sort` package from the standard library.
For example,
raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
vs := make([]*semver.Version, len(raw))
for i, r := range raw {
v, err := semver.NewVersion(r)
if err != nil {
t.Errorf("Error parsing version: %s", err)
}
vs[i] = v
}
sort.Sort(semver.Collection(vs))
Checking Version Constraints
Checking a version against version constraints is one of the most featureful
parts of the package.
c, err := semver.NewConstraint(">= 1.2.3")
if err != nil {
// Handle constraint not being parseable.
}
v, err := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parseable.
}
// Check if the version meets the constraints. The a variable will be true.
a := c.Check(v)
Basic Comparisons
There are two elements to the comparisons. First, a comparison string is a list
of comma separated and comparisons. These are then separated by || separated or
comparisons. For example, `">= 1.2, < 3.0.0 || >= 4.2.3"` is looking for a
comparison that's greater than or equal to 1.2 and less than 3.0.0 or is
greater than or equal to 4.2.3.
The basic comparisons are:
* `=`: equal (aliased to no operator)
* `!=`: not equal
* `>`: greater than
* `<`: less than
* `>=`: greater than or equal to
* `<=`: less than or equal to
Hyphen Range Comparisons
There are multiple methods to handle ranges and the first is hyphens ranges.
These look like:
* `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5`
* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4, <= 4.5`
Wildcards In Comparisons
The `x`, `X`, and `*` characters can be used as a wildcard character. This works
for all comparison operators. When used on the `=` operator it falls
back to the pack level comparison (see tilde below). For example,
* `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
* `>= 1.2.x` is equivalent to `>= 1.2.0`
* `<= 2.x` is equivalent to `<= 3`
* `*` is equivalent to `>= 0.0.0`
Tilde Range Comparisons (Patch)
The tilde (`~`) comparison operator is for patch level ranges when a minor
version is specified and major level changes when the minor number is missing.
For example,
* `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0`
* `~1` is equivalent to `>= 1, < 2`
* `~2.3` is equivalent to `>= 2.3, < 2.4`
* `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
* `~1.x` is equivalent to `>= 1, < 2`
Caret Range Comparisons (Major)
The caret (`^`) comparison operator is for major level changes. This is useful
when comparisons of API versions as a major change is API breaking. For example,
* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0`
* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0`
* `^2.3` is equivalent to `>= 2.3, < 3`
* `^2.x` is equivalent to `>= 2.0.0, < 3`
*/
package semver

1
vendor/github.com/Masterminds/semver/v3/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
_fuzz/

26
vendor/github.com/Masterminds/semver/v3/.golangci.yml generated vendored Normal file
View File

@ -0,0 +1,26 @@
run:
deadline: 2m
linters:
disable-all: true
enable:
- deadcode
- dupl
- errcheck
- gofmt
- goimports
- golint
- gosimple
- govet
- ineffassign
- misspell
- nakedret
- structcheck
- unused
- varcheck
linters-settings:
gofmt:
simplify: true
dupl:
threshold: 400

194
vendor/github.com/Masterminds/semver/v3/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,194 @@
# Changelog
## 3.1.1 (2020-11-23)
### Fixed
- #158: Fixed issue with generated regex operation order that could cause problem
## 3.1.0 (2020-04-15)
### Added
- #131: Add support for serializing/deserializing SQL (thanks @ryancurrah)
### Changed
- #148: More accurate validation messages on constraints
## 3.0.3 (2019-12-13)
### Fixed
- #141: Fixed issue with <= comparison
## 3.0.2 (2019-11-14)
### Fixed
- #134: Fixed broken constraint checking with ^0.0 (thanks @krmichelos)
## 3.0.1 (2019-09-13)
### Fixed
- #125: Fixes issue with module path for v3
## 3.0.0 (2019-09-12)
This is a major release of the semver package which includes API changes. The Go
API is compatible with ^1. The Go API was not changed because many people are using
`go get` without Go modules for their applications and API breaking changes cause
errors which we have or would need to support.
The changes in this release are the handling based on the data passed into the
functions. These are described in the added and changed sections below.
### Added
- StrictNewVersion function. This is similar to NewVersion but will return an
error if the version passed in is not a strict semantic version. For example,
1.2.3 would pass but v1.2.3 or 1.2 would fail because they are not strictly
speaking semantic versions. This function is faster, performs fewer operations,
and uses fewer allocations than NewVersion.
- Fuzzing has been performed on NewVersion, StrictNewVersion, and NewConstraint.
The Makefile contains the operations used. For more information on you can start
on Wikipedia at https://en.wikipedia.org/wiki/Fuzzing
- Now using Go modules
### Changed
- NewVersion has proper prerelease and metadata validation with error messages
to signal an issue with either of them
- ^ now operates using a similar set of rules to npm/js and Rust/Cargo. If the
version is >=1 the ^ ranges works the same as v1. For major versions of 0 the
rules have changed. The minor version is treated as the stable version unless
a patch is specified and then it is equivalent to =. One difference from npm/js
is that prereleases there are only to a specific version (e.g. 1.2.3).
Prereleases here look over multiple versions and follow semantic version
ordering rules. This pattern now follows along with the expected and requested
handling of this packaged by numerous users.
## 1.5.0 (2019-09-11)
### Added
- #103: Add basic fuzzing for `NewVersion()` (thanks @jesse-c)
### Changed
- #82: Clarify wildcard meaning in range constraints and update tests for it (thanks @greysteil)
- #83: Clarify caret operator range for pre-1.0.0 dependencies (thanks @greysteil)
- #72: Adding docs comment pointing to vert for a cli
- #71: Update the docs on pre-release comparator handling
- #89: Test with new go versions (thanks @thedevsaddam)
- #87: Added $ to ValidPrerelease for better validation (thanks @jeremycarroll)
### Fixed
- #78: Fix unchecked error in example code (thanks @ravron)
- #70: Fix the handling of pre-releases and the 0.0.0 release edge case
- #97: Fixed copyright file for proper display on GitHub
- #107: Fix handling prerelease when sorting alphanum and num
- #109: Fixed where Validate sometimes returns wrong message on error
## 1.4.2 (2018-04-10)
### Changed
- #72: Updated the docs to point to vert for a console appliaction
- #71: Update the docs on pre-release comparator handling
### Fixed
- #70: Fix the handling of pre-releases and the 0.0.0 release edge case
## 1.4.1 (2018-04-02)
### Fixed
- Fixed #64: Fix pre-release precedence issue (thanks @uudashr)
## 1.4.0 (2017-10-04)
### Changed
- #61: Update NewVersion to parse ints with a 64bit int size (thanks @zknill)
## 1.3.1 (2017-07-10)
### Fixed
- Fixed #57: number comparisons in prerelease sometimes inaccurate
## 1.3.0 (2017-05-02)
### Added
- #45: Added json (un)marshaling support (thanks @mh-cbon)
- Stability marker. See https://masterminds.github.io/stability/
### Fixed
- #51: Fix handling of single digit tilde constraint (thanks @dgodd)
### Changed
- #55: The godoc icon moved from png to svg
## 1.2.3 (2017-04-03)
### Fixed
- #46: Fixed 0.x.x and 0.0.x in constraints being treated as *
## Release 1.2.2 (2016-12-13)
### Fixed
- #34: Fixed issue where hyphen range was not working with pre-release parsing.
## Release 1.2.1 (2016-11-28)
### Fixed
- #24: Fixed edge case issue where constraint "> 0" does not handle "0.0.1-alpha"
properly.
## Release 1.2.0 (2016-11-04)
### Added
- #20: Added MustParse function for versions (thanks @adamreese)
- #15: Added increment methods on versions (thanks @mh-cbon)
### Fixed
- Issue #21: Per the SemVer spec (section 9) a pre-release is unstable and
might not satisfy the intended compatibility. The change here ignores pre-releases
on constraint checks (e.g., ~ or ^) when a pre-release is not part of the
constraint. For example, `^1.2.3` will ignore pre-releases while
`^1.2.3-alpha` will include them.
## Release 1.1.1 (2016-06-30)
### Changed
- Issue #9: Speed up version comparison performance (thanks @sdboyer)
- Issue #8: Added benchmarks (thanks @sdboyer)
- Updated Go Report Card URL to new location
- Updated Readme to add code snippet formatting (thanks @mh-cbon)
- Updating tagging to v[SemVer] structure for compatibility with other tools.
## Release 1.1.0 (2016-03-11)
- Issue #2: Implemented validation to provide reasons a versions failed a
constraint.
## Release 1.0.1 (2015-12-31)
- Fixed #1: * constraint failing on valid versions.
## Release 1.0.0 (2015-10-20)
- Initial release

37
vendor/github.com/Masterminds/semver/v3/Makefile generated vendored Normal file
View File

@ -0,0 +1,37 @@
GOPATH=$(shell go env GOPATH)
GOLANGCI_LINT=$(GOPATH)/bin/golangci-lint
GOFUZZBUILD = $(GOPATH)/bin/go-fuzz-build
GOFUZZ = $(GOPATH)/bin/go-fuzz
.PHONY: lint
lint: $(GOLANGCI_LINT)
@echo "==> Linting codebase"
@$(GOLANGCI_LINT) run
.PHONY: test
test:
@echo "==> Running tests"
GO111MODULE=on go test -v
.PHONY: test-cover
test-cover:
@echo "==> Running Tests with coverage"
GO111MODULE=on go test -cover .
.PHONY: fuzz
fuzz: $(GOFUZZBUILD) $(GOFUZZ)
@echo "==> Fuzz testing"
$(GOFUZZBUILD)
$(GOFUZZ) -workdir=_fuzz
$(GOLANGCI_LINT):
# Install golangci-lint. The configuration for it is in the .golangci.yml
# file in the root of the repository
echo ${GOPATH}
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.17.1
$(GOFUZZBUILD):
cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz-build
$(GOFUZZ):
cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-dep

244
vendor/github.com/Masterminds/semver/v3/README.md generated vendored Normal file
View File

@ -0,0 +1,244 @@
# SemVer
The `semver` package provides the ability to work with [Semantic Versions](http://semver.org) in Go. Specifically it provides the ability to:
* Parse semantic versions
* Sort semantic versions
* Check if a semantic version fits within a set of constraints
* Optionally work with a `v` prefix
[![Stability:
Active](https://masterminds.github.io/stability/active.svg)](https://masterminds.github.io/stability/active.html)
[![](https://github.com/Masterminds/semver/workflows/Tests/badge.svg)](https://github.com/Masterminds/semver/actions)
[![GoDoc](https://img.shields.io/static/v1?label=godoc&message=reference&color=blue)](https://pkg.go.dev/github.com/Masterminds/semver/v3)
[![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/semver)](https://goreportcard.com/report/github.com/Masterminds/semver)
If you are looking for a command line tool for version comparisons please see
[vert](https://github.com/Masterminds/vert) which uses this library.
## Package Versions
There are three major versions fo the `semver` package.
* 3.x.x is the new stable and active version. This version is focused on constraint
compatibility for range handling in other tools from other languages. It has
a similar API to the v1 releases. The development of this version is on the master
branch. The documentation for this version is below.
* 2.x was developed primarily for [dep](https://github.com/golang/dep). There are
no tagged releases and the development was performed by [@sdboyer](https://github.com/sdboyer).
There are API breaking changes from v1. This version lives on the [2.x branch](https://github.com/Masterminds/semver/tree/2.x).
* 1.x.x is the most widely used version with numerous tagged releases. This is the
previous stable and is still maintained for bug fixes. The development, to fix
bugs, occurs on the release-1 branch. You can read the documentation [here](https://github.com/Masterminds/semver/blob/release-1/README.md).
## Parsing Semantic Versions
There are two functions that can parse semantic versions. The `StrictNewVersion`
function only parses valid version 2 semantic versions as outlined in the
specification. The `NewVersion` function attempts to coerce a version into a
semantic version and parse it. For example, if there is a leading v or a version
listed without all 3 parts (e.g. `v1.2`) it will attempt to coerce it into a valid
semantic version (e.g., 1.2.0). In both cases a `Version` object is returned
that can be sorted, compared, and used in constraints.
When parsing a version an error is returned if there is an issue parsing the
version. For example,
v, err := semver.NewVersion("1.2.3-beta.1+build345")
The version object has methods to get the parts of the version, compare it to
other versions, convert the version back into a string, and get the original
string. Getting the original string is useful if the semantic version was coerced
into a valid form.
## Sorting Semantic Versions
A set of versions can be sorted using the `sort` package from the standard library.
For example,
```go
raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
vs := make([]*semver.Version, len(raw))
for i, r := range raw {
v, err := semver.NewVersion(r)
if err != nil {
t.Errorf("Error parsing version: %s", err)
}
vs[i] = v
}
sort.Sort(semver.Collection(vs))
```
## Checking Version Constraints
There are two methods for comparing versions. One uses comparison methods on
`Version` instances and the other uses `Constraints`. There are some important
differences to notes between these two methods of comparison.
1. When two versions are compared using functions such as `Compare`, `LessThan`,
and others it will follow the specification and always include prereleases
within the comparison. It will provide an answer that is valid with the
comparison section of the spec at https://semver.org/#spec-item-11
2. When constraint checking is used for checks or validation it will follow a
different set of rules that are common for ranges with tools like npm/js
and Rust/Cargo. This includes considering prereleases to be invalid if the
ranges does not include one. If you want to have it include pre-releases a
simple solution is to include `-0` in your range.
3. Constraint ranges can have some complex rules including the shorthand use of
~ and ^. For more details on those see the options below.
There are differences between the two methods or checking versions because the
comparison methods on `Version` follow the specification while comparison ranges
are not part of the specification. Different packages and tools have taken it
upon themselves to come up with range rules. This has resulted in differences.
For example, npm/js and Cargo/Rust follow similar patterns while PHP has a
different pattern for ^. The comparison features in this package follow the
npm/js and Cargo/Rust lead because applications using it have followed similar
patters with their versions.
Checking a version against version constraints is one of the most featureful
parts of the package.
```go
c, err := semver.NewConstraint(">= 1.2.3")
if err != nil {
// Handle constraint not being parsable.
}
v, err := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parsable.
}
// Check if the version meets the constraints. The a variable will be true.
a := c.Check(v)
```
### Basic Comparisons
There are two elements to the comparisons. First, a comparison string is a list
of space or comma separated AND comparisons. These are then separated by || (OR)
comparisons. For example, `">= 1.2 < 3.0.0 || >= 4.2.3"` is looking for a
comparison that's greater than or equal to 1.2 and less than 3.0.0 or is
greater than or equal to 4.2.3.
The basic comparisons are:
* `=`: equal (aliased to no operator)
* `!=`: not equal
* `>`: greater than
* `<`: less than
* `>=`: greater than or equal to
* `<=`: less than or equal to
### Working With Prerelease Versions
Pre-releases, for those not familiar with them, are used for software releases
prior to stable or generally available releases. Examples of prereleases include
development, alpha, beta, and release candidate releases. A prerelease may be
a version such as `1.2.3-beta.1` while the stable release would be `1.2.3`. In the
order of precedence, prereleases come before their associated releases. In this
example `1.2.3-beta.1 < 1.2.3`.
According to the Semantic Version specification prereleases may not be
API compliant with their release counterpart. It says,
> A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version.
SemVer comparisons using constraints without a prerelease comparator will skip
prerelease versions. For example, `>=1.2.3` will skip prereleases when looking
at a list of releases while `>=1.2.3-0` will evaluate and find prereleases.
The reason for the `0` as a pre-release version in the example comparison is
because pre-releases can only contain ASCII alphanumerics and hyphens (along with
`.` separators), per the spec. Sorting happens in ASCII sort order, again per the
spec. The lowest character is a `0` in ASCII sort order
(see an [ASCII Table](http://www.asciitable.com/))
Understanding ASCII sort ordering is important because A-Z comes before a-z. That
means `>=1.2.3-BETA` will return `1.2.3-alpha`. What you might expect from case
sensitivity doesn't apply here. This is due to ASCII sort ordering which is what
the spec specifies.
### Hyphen Range Comparisons
There are multiple methods to handle ranges and the first is hyphens ranges.
These look like:
* `1.2 - 1.4.5` which is equivalent to `>= 1.2 <= 1.4.5`
* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4 <= 4.5`
### Wildcards In Comparisons
The `x`, `X`, and `*` characters can be used as a wildcard character. This works
for all comparison operators. When used on the `=` operator it falls
back to the patch level comparison (see tilde below). For example,
* `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
* `>= 1.2.x` is equivalent to `>= 1.2.0`
* `<= 2.x` is equivalent to `< 3`
* `*` is equivalent to `>= 0.0.0`
### Tilde Range Comparisons (Patch)
The tilde (`~`) comparison operator is for patch level ranges when a minor
version is specified and major level changes when the minor number is missing.
For example,
* `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0`
* `~1` is equivalent to `>= 1, < 2`
* `~2.3` is equivalent to `>= 2.3, < 2.4`
* `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
* `~1.x` is equivalent to `>= 1, < 2`
### Caret Range Comparisons (Major)
The caret (`^`) comparison operator is for major level changes once a stable
(1.0.0) release has occurred. Prior to a 1.0.0 release the minor versions acts
as the API stability level. This is useful when comparisons of API versions as a
major change is API breaking. For example,
* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0`
* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0`
* `^2.3` is equivalent to `>= 2.3, < 3`
* `^2.x` is equivalent to `>= 2.0.0, < 3`
* `^0.2.3` is equivalent to `>=0.2.3 <0.3.0`
* `^0.2` is equivalent to `>=0.2.0 <0.3.0`
* `^0.0.3` is equivalent to `>=0.0.3 <0.0.4`
* `^0.0` is equivalent to `>=0.0.0 <0.1.0`
* `^0` is equivalent to `>=0.0.0 <1.0.0`
## Validation
In addition to testing a version against a constraint, a version can be validated
against a constraint. When validation fails a slice of errors containing why a
version didn't meet the constraint is returned. For example,
```go
c, err := semver.NewConstraint("<= 1.2.3, >= 1.4")
if err != nil {
// Handle constraint not being parseable.
}
v, err := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parseable.
}
// Validate a version against a constraint.
a, msgs := c.Validate(v)
// a is false
for _, m := range msgs {
fmt.Println(m)
// Loops over the errors which would read
// "1.3 is greater than 1.2.3"
// "1.3 is less than 1.4"
}
```
## Contribute
If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues)
or [create a pull request](https://github.com/Masterminds/semver/pulls).

568
vendor/github.com/Masterminds/semver/v3/constraints.go generated vendored Normal file
View File

@ -0,0 +1,568 @@
package semver
import (
"bytes"
"errors"
"fmt"
"regexp"
"strings"
)
// Constraints is one or more constraint that a semantic version can be
// checked against.
type Constraints struct {
constraints [][]*constraint
}
// NewConstraint returns a Constraints instance that a Version instance can
// be checked against. If there is a parse error it will be returned.
func NewConstraint(c string) (*Constraints, error) {
// Rewrite - ranges into a comparison operation.
c = rewriteRange(c)
ors := strings.Split(c, "||")
or := make([][]*constraint, len(ors))
for k, v := range ors {
// TODO: Find a way to validate and fetch all the constraints in a simpler form
// Validate the segment
if !validConstraintRegex.MatchString(v) {
return nil, fmt.Errorf("improper constraint: %s", v)
}
cs := findConstraintRegex.FindAllString(v, -1)
if cs == nil {
cs = append(cs, v)
}
result := make([]*constraint, len(cs))
for i, s := range cs {
pc, err := parseConstraint(s)
if err != nil {
return nil, err
}
result[i] = pc
}
or[k] = result
}
o := &Constraints{constraints: or}
return o, nil
}
// Check tests if a version satisfies the constraints.
func (cs Constraints) Check(v *Version) bool {
// TODO(mattfarina): For v4 of this library consolidate the Check and Validate
// functions as the underlying functions make that possible now.
// loop over the ORs and check the inner ANDs
for _, o := range cs.constraints {
joy := true
for _, c := range o {
if check, _ := c.check(v); !check {
joy = false
break
}
}
if joy {
return true
}
}
return false
}
// Validate checks if a version satisfies a constraint. If not a slice of
// reasons for the failure are returned in addition to a bool.
func (cs Constraints) Validate(v *Version) (bool, []error) {
// loop over the ORs and check the inner ANDs
var e []error
// Capture the prerelease message only once. When it happens the first time
// this var is marked
var prerelesase bool
for _, o := range cs.constraints {
joy := true
for _, c := range o {
// Before running the check handle the case there the version is
// a prerelease and the check is not searching for prereleases.
if c.con.pre == "" && v.pre != "" {
if !prerelesase {
em := fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
e = append(e, em)
prerelesase = true
}
joy = false
} else {
if _, err := c.check(v); err != nil {
e = append(e, err)
joy = false
}
}
}
if joy {
return true, []error{}
}
}
return false, e
}
func (cs Constraints) String() string {
buf := make([]string, len(cs.constraints))
var tmp bytes.Buffer
for k, v := range cs.constraints {
tmp.Reset()
vlen := len(v)
for kk, c := range v {
tmp.WriteString(c.string())
// Space separate the AND conditions
if vlen > 1 && kk < vlen-1 {
tmp.WriteString(" ")
}
}
buf[k] = tmp.String()
}
return strings.Join(buf, " || ")
}
var constraintOps map[string]cfunc
var constraintRegex *regexp.Regexp
var constraintRangeRegex *regexp.Regexp
// Used to find individual constraints within a multi-constraint string
var findConstraintRegex *regexp.Regexp
// Used to validate an segment of ANDs is valid
var validConstraintRegex *regexp.Regexp
const cvRegex string = `v?([0-9|x|X|\*]+)(\.[0-9|x|X|\*]+)?(\.[0-9|x|X|\*]+)?` +
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
func init() {
constraintOps = map[string]cfunc{
"": constraintTildeOrEqual,
"=": constraintTildeOrEqual,
"!=": constraintNotEqual,
">": constraintGreaterThan,
"<": constraintLessThan,
">=": constraintGreaterThanEqual,
"=>": constraintGreaterThanEqual,
"<=": constraintLessThanEqual,
"=<": constraintLessThanEqual,
"~": constraintTilde,
"~>": constraintTilde,
"^": constraintCaret,
}
ops := `=||!=|>|<|>=|=>|<=|=<|~|~>|\^`
constraintRegex = regexp.MustCompile(fmt.Sprintf(
`^\s*(%s)\s*(%s)\s*$`,
ops,
cvRegex))
constraintRangeRegex = regexp.MustCompile(fmt.Sprintf(
`\s*(%s)\s+-\s+(%s)\s*`,
cvRegex, cvRegex))
findConstraintRegex = regexp.MustCompile(fmt.Sprintf(
`(%s)\s*(%s)`,
ops,
cvRegex))
validConstraintRegex = regexp.MustCompile(fmt.Sprintf(
`^(\s*(%s)\s*(%s)\s*\,?)+$`,
ops,
cvRegex))
}
// An individual constraint
type constraint struct {
// The version used in the constraint check. For example, if a constraint
// is '<= 2.0.0' the con a version instance representing 2.0.0.
con *Version
// The original parsed version (e.g., 4.x from != 4.x)
orig string
// The original operator for the constraint
origfunc string
// When an x is used as part of the version (e.g., 1.x)
minorDirty bool
dirty bool
patchDirty bool
}
// Check if a version meets the constraint
func (c *constraint) check(v *Version) (bool, error) {
return constraintOps[c.origfunc](v, c)
}
// String prints an individual constraint into a string
func (c *constraint) string() string {
return c.origfunc + c.orig
}
type cfunc func(v *Version, c *constraint) (bool, error)
func parseConstraint(c string) (*constraint, error) {
if len(c) > 0 {
m := constraintRegex.FindStringSubmatch(c)
if m == nil {
return nil, fmt.Errorf("improper constraint: %s", c)
}
cs := &constraint{
orig: m[2],
origfunc: m[1],
}
ver := m[2]
minorDirty := false
patchDirty := false
dirty := false
if isX(m[3]) || m[3] == "" {
ver = "0.0.0"
dirty = true
} else if isX(strings.TrimPrefix(m[4], ".")) || m[4] == "" {
minorDirty = true
dirty = true
ver = fmt.Sprintf("%s.0.0%s", m[3], m[6])
} else if isX(strings.TrimPrefix(m[5], ".")) || m[5] == "" {
dirty = true
patchDirty = true
ver = fmt.Sprintf("%s%s.0%s", m[3], m[4], m[6])
}
con, err := NewVersion(ver)
if err != nil {
// The constraintRegex should catch any regex parsing errors. So,
// we should never get here.
return nil, errors.New("constraint Parser Error")
}
cs.con = con
cs.minorDirty = minorDirty
cs.patchDirty = patchDirty
cs.dirty = dirty
return cs, nil
}
// The rest is the special case where an empty string was passed in which
// is equivalent to * or >=0.0.0
con, err := StrictNewVersion("0.0.0")
if err != nil {
// The constraintRegex should catch any regex parsing errors. So,
// we should never get here.
return nil, errors.New("constraint Parser Error")
}
cs := &constraint{
con: con,
orig: c,
origfunc: "",
minorDirty: false,
patchDirty: false,
dirty: true,
}
return cs, nil
}
// Constraint functions
func constraintNotEqual(v *Version, c *constraint) (bool, error) {
if c.dirty {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
if c.con.Major() != v.Major() {
return true, nil
}
if c.con.Minor() != v.Minor() && !c.minorDirty {
return true, nil
} else if c.minorDirty {
return false, fmt.Errorf("%s is equal to %s", v, c.orig)
} else if c.con.Patch() != v.Patch() && !c.patchDirty {
return true, nil
} else if c.patchDirty {
// Need to handle prereleases if present
if v.Prerelease() != "" || c.con.Prerelease() != "" {
eq := comparePrerelease(v.Prerelease(), c.con.Prerelease()) != 0
if eq {
return true, nil
}
return false, fmt.Errorf("%s is equal to %s", v, c.orig)
}
return false, fmt.Errorf("%s is equal to %s", v, c.orig)
}
}
eq := v.Equal(c.con)
if eq {
return false, fmt.Errorf("%s is equal to %s", v, c.orig)
}
return true, nil
}
func constraintGreaterThan(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
var eq bool
if !c.dirty {
eq = v.Compare(c.con) == 1
if eq {
return true, nil
}
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
}
if v.Major() > c.con.Major() {
return true, nil
} else if v.Major() < c.con.Major() {
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
} else if c.minorDirty {
// This is a range case such as >11. When the version is something like
// 11.1.0 is it not > 11. For that we would need 12 or higher
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
} else if c.patchDirty {
// This is for ranges such as >11.1. A version of 11.1.1 is not greater
// which one of 11.2.1 is greater
eq = v.Minor() > c.con.Minor()
if eq {
return true, nil
}
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
}
// If we have gotten here we are not comparing pre-preleases and can use the
// Compare function to accomplish that.
eq = v.Compare(c.con) == 1
if eq {
return true, nil
}
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
}
func constraintLessThan(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
eq := v.Compare(c.con) < 0
if eq {
return true, nil
}
return false, fmt.Errorf("%s is greater than or equal to %s", v, c.orig)
}
func constraintGreaterThanEqual(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
eq := v.Compare(c.con) >= 0
if eq {
return true, nil
}
return false, fmt.Errorf("%s is less than %s", v, c.orig)
}
func constraintLessThanEqual(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
var eq bool
if !c.dirty {
eq = v.Compare(c.con) <= 0
if eq {
return true, nil
}
return false, fmt.Errorf("%s is greater than %s", v, c.orig)
}
if v.Major() > c.con.Major() {
return false, fmt.Errorf("%s is greater than %s", v, c.orig)
} else if v.Major() == c.con.Major() && v.Minor() > c.con.Minor() && !c.minorDirty {
return false, fmt.Errorf("%s is greater than %s", v, c.orig)
}
return true, nil
}
// ~*, ~>* --> >= 0.0.0 (any)
// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0, <3.0.0
// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0, <2.1.0
// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0, <1.3.0
// ~1.2.3, ~>1.2.3 --> >=1.2.3, <1.3.0
// ~1.2.0, ~>1.2.0 --> >=1.2.0, <1.3.0
func constraintTilde(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
if v.LessThan(c.con) {
return false, fmt.Errorf("%s is less than %s", v, c.orig)
}
// ~0.0.0 is a special case where all constraints are accepted. It's
// equivalent to >= 0.0.0.
if c.con.Major() == 0 && c.con.Minor() == 0 && c.con.Patch() == 0 &&
!c.minorDirty && !c.patchDirty {
return true, nil
}
if v.Major() != c.con.Major() {
return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
}
if v.Minor() != c.con.Minor() && !c.minorDirty {
return false, fmt.Errorf("%s does not have same major and minor version as %s", v, c.orig)
}
return true, nil
}
// When there is a .x (dirty) status it automatically opts in to ~. Otherwise
// it's a straight =
func constraintTildeOrEqual(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
if c.dirty {
return constraintTilde(v, c)
}
eq := v.Equal(c.con)
if eq {
return true, nil
}
return false, fmt.Errorf("%s is not equal to %s", v, c.orig)
}
// ^* --> (any)
// ^1.2.3 --> >=1.2.3 <2.0.0
// ^1.2 --> >=1.2.0 <2.0.0
// ^1 --> >=1.0.0 <2.0.0
// ^0.2.3 --> >=0.2.3 <0.3.0
// ^0.2 --> >=0.2.0 <0.3.0
// ^0.0.3 --> >=0.0.3 <0.0.4
// ^0.0 --> >=0.0.0 <0.1.0
// ^0 --> >=0.0.0 <1.0.0
func constraintCaret(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
// This less than handles prereleases
if v.LessThan(c.con) {
return false, fmt.Errorf("%s is less than %s", v, c.orig)
}
var eq bool
// ^ when the major > 0 is >=x.y.z < x+1
if c.con.Major() > 0 || c.minorDirty {
// ^ has to be within a major range for > 0. Everything less than was
// filtered out with the LessThan call above. This filters out those
// that greater but not within the same major range.
eq = v.Major() == c.con.Major()
if eq {
return true, nil
}
return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
}
// ^ when the major is 0 and minor > 0 is >=0.y.z < 0.y+1
if c.con.Major() == 0 && v.Major() > 0 {
return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
}
// If the con Minor is > 0 it is not dirty
if c.con.Minor() > 0 || c.patchDirty {
eq = v.Minor() == c.con.Minor()
if eq {
return true, nil
}
return false, fmt.Errorf("%s does not have same minor version as %s. Expected minor versions to match when constraint major version is 0", v, c.orig)
}
// At this point the major is 0 and the minor is 0 and not dirty. The patch
// is not dirty so we need to check if they are equal. If they are not equal
eq = c.con.Patch() == v.Patch()
if eq {
return true, nil
}
return false, fmt.Errorf("%s does not equal %s. Expect version and constraint to equal when major and minor versions are 0", v, c.orig)
}
func isX(x string) bool {
switch x {
case "x", "*", "X":
return true
default:
return false
}
}
func rewriteRange(i string) string {
m := constraintRangeRegex.FindAllStringSubmatch(i, -1)
if m == nil {
return i
}
o := i
for _, v := range m {
t := fmt.Sprintf(">= %s, <= %s", v[1], v[11])
o = strings.Replace(o, v[0], t, 1)
}
return o
}

184
vendor/github.com/Masterminds/semver/v3/doc.go generated vendored Normal file
View File

@ -0,0 +1,184 @@
/*
Package semver provides the ability to work with Semantic Versions (http://semver.org) in Go.
Specifically it provides the ability to:
* Parse semantic versions
* Sort semantic versions
* Check if a semantic version fits within a set of constraints
* Optionally work with a `v` prefix
Parsing Semantic Versions
There are two functions that can parse semantic versions. The `StrictNewVersion`
function only parses valid version 2 semantic versions as outlined in the
specification. The `NewVersion` function attempts to coerce a version into a
semantic version and parse it. For example, if there is a leading v or a version
listed without all 3 parts (e.g. 1.2) it will attempt to coerce it into a valid
semantic version (e.g., 1.2.0). In both cases a `Version` object is returned
that can be sorted, compared, and used in constraints.
When parsing a version an optional error can be returned if there is an issue
parsing the version. For example,
v, err := semver.NewVersion("1.2.3-beta.1+b345")
The version object has methods to get the parts of the version, compare it to
other versions, convert the version back into a string, and get the original
string. For more details please see the documentation
at https://godoc.org/github.com/Masterminds/semver.
Sorting Semantic Versions
A set of versions can be sorted using the `sort` package from the standard library.
For example,
raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
vs := make([]*semver.Version, len(raw))
for i, r := range raw {
v, err := semver.NewVersion(r)
if err != nil {
t.Errorf("Error parsing version: %s", err)
}
vs[i] = v
}
sort.Sort(semver.Collection(vs))
Checking Version Constraints and Comparing Versions
There are two methods for comparing versions. One uses comparison methods on
`Version` instances and the other is using Constraints. There are some important
differences to notes between these two methods of comparison.
1. When two versions are compared using functions such as `Compare`, `LessThan`,
and others it will follow the specification and always include prereleases
within the comparison. It will provide an answer valid with the comparison
spec section at https://semver.org/#spec-item-11
2. When constraint checking is used for checks or validation it will follow a
different set of rules that are common for ranges with tools like npm/js
and Rust/Cargo. This includes considering prereleases to be invalid if the
ranges does not include on. If you want to have it include pre-releases a
simple solution is to include `-0` in your range.
3. Constraint ranges can have some complex rules including the shorthard use of
~ and ^. For more details on those see the options below.
There are differences between the two methods or checking versions because the
comparison methods on `Version` follow the specification while comparison ranges
are not part of the specification. Different packages and tools have taken it
upon themselves to come up with range rules. This has resulted in differences.
For example, npm/js and Cargo/Rust follow similar patterns which PHP has a
different pattern for ^. The comparison features in this package follow the
npm/js and Cargo/Rust lead because applications using it have followed similar
patters with their versions.
Checking a version against version constraints is one of the most featureful
parts of the package.
c, err := semver.NewConstraint(">= 1.2.3")
if err != nil {
// Handle constraint not being parsable.
}
v, err := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parsable.
}
// Check if the version meets the constraints. The a variable will be true.
a := c.Check(v)
Basic Comparisons
There are two elements to the comparisons. First, a comparison string is a list
of comma or space separated AND comparisons. These are then separated by || (OR)
comparisons. For example, `">= 1.2 < 3.0.0 || >= 4.2.3"` is looking for a
comparison that's greater than or equal to 1.2 and less than 3.0.0 or is
greater than or equal to 4.2.3. This can also be written as
`">= 1.2, < 3.0.0 || >= 4.2.3"`
The basic comparisons are:
* `=`: equal (aliased to no operator)
* `!=`: not equal
* `>`: greater than
* `<`: less than
* `>=`: greater than or equal to
* `<=`: less than or equal to
Hyphen Range Comparisons
There are multiple methods to handle ranges and the first is hyphens ranges.
These look like:
* `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5`
* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4 <= 4.5`
Wildcards In Comparisons
The `x`, `X`, and `*` characters can be used as a wildcard character. This works
for all comparison operators. When used on the `=` operator it falls
back to the tilde operation. For example,
* `1.2.x` is equivalent to `>= 1.2.0 < 1.3.0`
* `>= 1.2.x` is equivalent to `>= 1.2.0`
* `<= 2.x` is equivalent to `<= 3`
* `*` is equivalent to `>= 0.0.0`
Tilde Range Comparisons (Patch)
The tilde (`~`) comparison operator is for patch level ranges when a minor
version is specified and major level changes when the minor number is missing.
For example,
* `~1.2.3` is equivalent to `>= 1.2.3 < 1.3.0`
* `~1` is equivalent to `>= 1, < 2`
* `~2.3` is equivalent to `>= 2.3 < 2.4`
* `~1.2.x` is equivalent to `>= 1.2.0 < 1.3.0`
* `~1.x` is equivalent to `>= 1 < 2`
Caret Range Comparisons (Major)
The caret (`^`) comparison operator is for major level changes once a stable
(1.0.0) release has occurred. Prior to a 1.0.0 release the minor versions acts
as the API stability level. This is useful when comparisons of API versions as a
major change is API breaking. For example,
* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0`
* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0`
* `^2.3` is equivalent to `>= 2.3, < 3`
* `^2.x` is equivalent to `>= 2.0.0, < 3`
* `^0.2.3` is equivalent to `>=0.2.3 <0.3.0`
* `^0.2` is equivalent to `>=0.2.0 <0.3.0`
* `^0.0.3` is equivalent to `>=0.0.3 <0.0.4`
* `^0.0` is equivalent to `>=0.0.0 <0.1.0`
* `^0` is equivalent to `>=0.0.0 <1.0.0`
Validation
In addition to testing a version against a constraint, a version can be validated
against a constraint. When validation fails a slice of errors containing why a
version didn't meet the constraint is returned. For example,
c, err := semver.NewConstraint("<= 1.2.3, >= 1.4")
if err != nil {
// Handle constraint not being parseable.
}
v, _ := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parseable.
}
// Validate a version against a constraint.
a, msgs := c.Validate(v)
// a is false
for _, m := range msgs {
fmt.Println(m)
// Loops over the errors which would read
// "1.3 is greater than 1.2.3"
// "1.3 is less than 1.4"
}
*/
package semver

22
vendor/github.com/Masterminds/semver/v3/fuzz.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
// +build gofuzz
package semver
func Fuzz(data []byte) int {
d := string(data)
// Test NewVersion
_, _ = NewVersion(d)
// Test StrictNewVersion
_, _ = StrictNewVersion(d)
// Test NewConstraint
_, _ = NewConstraint(d)
// The return value should be 0 normally, 1 if the priority in future tests
// should be increased, and -1 if future tests should skip passing in that
// data. We do not have a reason to change priority so 0 is always returned.
// There are example tests that do this.
return 0
}

View File

@ -2,6 +2,7 @@ package semver
import (
"bytes"
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
@ -13,13 +14,23 @@ import (
// The compiled version of the regex created at init() is cached here so it
// only needs to be created once.
var versionRegex *regexp.Regexp
var validPrereleaseRegex *regexp.Regexp
var (
// ErrInvalidSemVer is returned a version is found to be invalid when
// being parsed.
ErrInvalidSemVer = errors.New("Invalid Semantic Version")
// ErrEmptyString is returned when an empty string is passed in for parsing.
ErrEmptyString = errors.New("Version string empty")
// ErrInvalidCharacters is returned when invalid characters are found as
// part of a version
ErrInvalidCharacters = errors.New("Invalid characters in version")
// ErrSegmentStartsZero is returned when a version segment starts with 0.
// This is invalid in SemVer.
ErrSegmentStartsZero = errors.New("Version segment starts with 0")
// ErrInvalidMetadata is returned when the metadata is an invalid format
ErrInvalidMetadata = errors.New("Invalid Metadata string")
@ -27,30 +38,121 @@ var (
ErrInvalidPrerelease = errors.New("Invalid Prerelease string")
)
// SemVerRegex is the regular expression used to parse a semantic version.
const SemVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` +
// semVerRegex is the regular expression used to parse a semantic version.
const semVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` +
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
// ValidPrerelease is the regular expression which validates
// both prerelease and metadata values.
const ValidPrerelease string = `^([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*)$`
// Version represents a single semantic version.
type Version struct {
major, minor, patch int64
major, minor, patch uint64
pre string
metadata string
original string
}
func init() {
versionRegex = regexp.MustCompile("^" + SemVerRegex + "$")
validPrereleaseRegex = regexp.MustCompile(ValidPrerelease)
versionRegex = regexp.MustCompile("^" + semVerRegex + "$")
}
const num string = "0123456789"
const allowed string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" + num
// StrictNewVersion parses a given version and returns an instance of Version or
// an error if unable to parse the version. Only parses valid semantic versions.
// Performs checking that can find errors within the version.
// If you want to coerce a version, such as 1 or 1.2, and perse that as the 1.x
// releases of semver provided use the NewSemver() function.
func StrictNewVersion(v string) (*Version, error) {
// Parsing here does not use RegEx in order to increase performance and reduce
// allocations.
if len(v) == 0 {
return nil, ErrEmptyString
}
// Split the parts into [0]major, [1]minor, and [2]patch,prerelease,build
parts := strings.SplitN(v, ".", 3)
if len(parts) != 3 {
return nil, ErrInvalidSemVer
}
sv := &Version{
original: v,
}
// check for prerelease or build metadata
var extra []string
if strings.ContainsAny(parts[2], "-+") {
// Start with the build metadata first as it needs to be on the right
extra = strings.SplitN(parts[2], "+", 2)
if len(extra) > 1 {
// build metadata found
sv.metadata = extra[1]
parts[2] = extra[0]
}
extra = strings.SplitN(parts[2], "-", 2)
if len(extra) > 1 {
// prerelease found
sv.pre = extra[1]
parts[2] = extra[0]
}
}
// Validate the number segments are valid. This includes only having positive
// numbers and no leading 0's.
for _, p := range parts {
if !containsOnly(p, num) {
return nil, ErrInvalidCharacters
}
if len(p) > 1 && p[0] == '0' {
return nil, ErrSegmentStartsZero
}
}
// Extract the major, minor, and patch elements onto the returned Version
var err error
sv.major, err = strconv.ParseUint(parts[0], 10, 64)
if err != nil {
return nil, err
}
sv.minor, err = strconv.ParseUint(parts[1], 10, 64)
if err != nil {
return nil, err
}
sv.patch, err = strconv.ParseUint(parts[2], 10, 64)
if err != nil {
return nil, err
}
// No prerelease or build metadata found so returning now as a fastpath.
if sv.pre == "" && sv.metadata == "" {
return sv, nil
}
if sv.pre != "" {
if err = validatePrerelease(sv.pre); err != nil {
return nil, err
}
}
if sv.metadata != "" {
if err = validateMetadata(sv.metadata); err != nil {
return nil, err
}
}
return sv, nil
}
// NewVersion parses a given version and returns an instance of Version or
// an error if unable to parse the version.
// an error if unable to parse the version. If the version is SemVer-ish it
// attempts to convert it to SemVer. If you want to validate it was a strict
// semantic version at parse time see StrictNewVersion().
func NewVersion(v string) (*Version, error) {
m := versionRegex.FindStringSubmatch(v)
if m == nil {
@ -63,33 +165,45 @@ func NewVersion(v string) (*Version, error) {
original: v,
}
var temp int64
temp, err := strconv.ParseInt(m[1], 10, 64)
var err error
sv.major, err = strconv.ParseUint(m[1], 10, 64)
if err != nil {
return nil, fmt.Errorf("Error parsing version segment: %s", err)
}
sv.major = temp
if m[2] != "" {
temp, err = strconv.ParseInt(strings.TrimPrefix(m[2], "."), 10, 64)
sv.minor, err = strconv.ParseUint(strings.TrimPrefix(m[2], "."), 10, 64)
if err != nil {
return nil, fmt.Errorf("Error parsing version segment: %s", err)
}
sv.minor = temp
} else {
sv.minor = 0
}
if m[3] != "" {
temp, err = strconv.ParseInt(strings.TrimPrefix(m[3], "."), 10, 64)
sv.patch, err = strconv.ParseUint(strings.TrimPrefix(m[3], "."), 10, 64)
if err != nil {
return nil, fmt.Errorf("Error parsing version segment: %s", err)
}
sv.patch = temp
} else {
sv.patch = 0
}
// Perform some basic due diligence on the extra parts to ensure they are
// valid.
if sv.pre != "" {
if err = validatePrerelease(sv.pre); err != nil {
return nil, err
}
}
if sv.metadata != "" {
if err = validateMetadata(sv.metadata); err != nil {
return nil, err
}
}
return sv, nil
}
@ -107,7 +221,7 @@ func MustParse(v string) *Version {
// See the Original() method to retrieve the original value. Semantic Versions
// don't contain a leading v per the spec. Instead it's optional on
// implementation.
func (v *Version) String() string {
func (v Version) String() string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "%d.%d.%d", v.major, v.minor, v.patch)
@ -127,32 +241,32 @@ func (v *Version) Original() string {
}
// Major returns the major version.
func (v *Version) Major() int64 {
func (v Version) Major() uint64 {
return v.major
}
// Minor returns the minor version.
func (v *Version) Minor() int64 {
func (v Version) Minor() uint64 {
return v.minor
}
// Patch returns the patch version.
func (v *Version) Patch() int64 {
func (v Version) Patch() uint64 {
return v.patch
}
// Prerelease returns the pre-release version.
func (v *Version) Prerelease() string {
func (v Version) Prerelease() string {
return v.pre
}
// Metadata returns the metadata on the version.
func (v *Version) Metadata() string {
func (v Version) Metadata() string {
return v.metadata
}
// originalVPrefix returns the original 'v' prefix if any.
func (v *Version) originalVPrefix() string {
func (v Version) originalVPrefix() string {
// Note, only lowercase v is supported as a prefix by the parser.
if v.original != "" && v.original[:1] == "v" {
@ -165,7 +279,7 @@ func (v *Version) originalVPrefix() string {
// If the current version does not have prerelease/metadata information,
// it unsets metadata and prerelease values, increments patch number.
// If the current version has any of prerelease or metadata information,
// it unsets both values and keeps curent patch value
// it unsets both values and keeps current patch value
func (v Version) IncPatch() Version {
vNext := v
// according to http://semver.org/#spec-item-9
@ -217,11 +331,13 @@ func (v Version) IncMajor() Version {
}
// SetPrerelease defines the prerelease value.
// Value must not include the required 'hypen' prefix.
// Value must not include the required 'hyphen' prefix.
func (v Version) SetPrerelease(prerelease string) (Version, error) {
vNext := v
if len(prerelease) > 0 && !validPrereleaseRegex.MatchString(prerelease) {
return vNext, ErrInvalidPrerelease
if len(prerelease) > 0 {
if err := validatePrerelease(prerelease); err != nil {
return vNext, err
}
}
vNext.pre = prerelease
vNext.original = v.originalVPrefix() + "" + vNext.String()
@ -232,8 +348,10 @@ func (v Version) SetPrerelease(prerelease string) (Version, error) {
// Value must not include the required 'plus' prefix.
func (v Version) SetMetadata(metadata string) (Version, error) {
vNext := v
if len(metadata) > 0 && !validPrereleaseRegex.MatchString(metadata) {
return vNext, ErrInvalidMetadata
if len(metadata) > 0 {
if err := validateMetadata(metadata); err != nil {
return vNext, err
}
}
vNext.metadata = metadata
vNext.original = v.originalVPrefix() + "" + vNext.String()
@ -261,7 +379,9 @@ func (v *Version) Equal(o *Version) bool {
// the version smaller, equal, or larger than the other version.
//
// Versions are compared by X.Y.Z. Build metadata is ignored. Prerelease is
// lower than the version without a prerelease.
// lower than the version without a prerelease. Compare always takes into account
// prereleases. If you want to work with ranges using typical range syntaxes that
// skip prereleases if the range is not looking for them use constraints.
func (v *Version) Compare(o *Version) int {
// Compare the major, minor, and patch version for differences. If a
// difference is found return the comparison.
@ -308,16 +428,37 @@ func (v *Version) UnmarshalJSON(b []byte) error {
v.pre = temp.pre
v.metadata = temp.metadata
v.original = temp.original
temp = nil
return nil
}
// MarshalJSON implements JSON.Marshaler interface.
func (v *Version) MarshalJSON() ([]byte, error) {
func (v Version) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
func compareSegment(v, o int64) int {
// Scan implements the SQL.Scanner interface.
func (v *Version) Scan(value interface{}) error {
var s string
s, _ = value.(string)
temp, err := NewVersion(s)
if err != nil {
return err
}
v.major = temp.major
v.minor = temp.minor
v.patch = temp.patch
v.pre = temp.pre
v.metadata = temp.metadata
v.original = temp.original
return nil
}
// Value implements the Driver.Valuer interface.
func (v Version) Value() (driver.Value, error) {
return v.String(), nil
}
func compareSegment(v, o uint64) int {
if v < o {
return -1
}
@ -423,3 +564,43 @@ func comparePrePart(s, o string) int {
return -1
}
// Like strings.ContainsAny but does an only instead of any.
func containsOnly(s string, comp string) bool {
return strings.IndexFunc(s, func(r rune) bool {
return !strings.ContainsRune(comp, r)
}) == -1
}
// From the spec, "Identifiers MUST comprise only
// ASCII alphanumerics and hyphen [0-9A-Za-z-]. Identifiers MUST NOT be empty.
// Numeric identifiers MUST NOT include leading zeroes.". These segments can
// be dot separated.
func validatePrerelease(p string) error {
eparts := strings.Split(p, ".")
for _, p := range eparts {
if containsOnly(p, num) {
if len(p) > 1 && p[0] == '0' {
return ErrSegmentStartsZero
}
} else if !containsOnly(p, allowed) {
return ErrInvalidPrerelease
}
}
return nil
}
// From the spec, "Build metadata MAY be denoted by
// appending a plus sign and a series of dot separated identifiers immediately
// following the patch or pre-release version. Identifiers MUST comprise only
// ASCII alphanumerics and hyphen [0-9A-Za-z-]. Identifiers MUST NOT be empty."
func validateMetadata(m string) error {
eparts := strings.Split(m, ".")
for _, p := range eparts {
if !containsOnly(p, allowed) {
return ErrInvalidMetadata
}
}
return nil
}

View File

@ -1,10 +0,0 @@
// +build gofuzz
package semver
func Fuzz(data []byte) int {
if _, err := NewVersion(string(data)); err != nil {
return 0
}
return 1
}

View File

@ -1,26 +0,0 @@
language: go
go:
- 1.9.x
- 1.10.x
- 1.11.x
- 1.12.x
- 1.13.x
- tip
# Setting sudo access to false will let Travis CI use containers rather than
# VMs to run the tests. For more details see:
# - http://docs.travis-ci.com/user/workers/container-based-infrastructure/
# - http://docs.travis-ci.com/user/workers/standard-infrastructure/
sudo: false
script:
- make setup test
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/06e3328629952dabe3e0
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: never # options: [always|never|change] default: always

View File

@ -1,13 +0,0 @@
HAS_GLIDE := $(shell command -v glide;)
.PHONY: test
test:
go test -v .
.PHONY: setup
setup:
ifndef HAS_GLIDE
go get -u github.com/Masterminds/glide
endif
glide install

View File

@ -1,26 +0,0 @@
version: build-{build}.{branch}
clone_folder: C:\gopath\src\github.com\Masterminds\sprig
shallow_clone: true
environment:
GOPATH: C:\gopath
platform:
- x64
install:
- go get -u github.com/Masterminds/glide
- set PATH=%GOPATH%\bin;%PATH%
- go version
- go env
build_script:
- glide install
- go install ./...
test_script:
- go test -v
deploy: off

View File

@ -1,19 +0,0 @@
package: github.com/Masterminds/sprig
import:
- package: github.com/Masterminds/goutils
version: ^1.0.0
- package: github.com/google/uuid
version: ^1.0.0
- package: golang.org/x/crypto
subpackages:
- scrypt
- package: github.com/Masterminds/semver
version: ^v1.2.2
- package: github.com/stretchr/testify
version: ^v1.2.2
- package: github.com/imdario/mergo
version: ~0.3.7
- package: github.com/huandu/xstrings
version: ^1.2
- package: github.com/mitchellh/copystructure
version: ^1.0.0

View File

@ -1,169 +0,0 @@
package sprig
import (
"fmt"
"math"
"reflect"
"strconv"
)
// toFloat64 converts 64-bit floats
func toFloat64(v interface{}) float64 {
if str, ok := v.(string); ok {
iv, err := strconv.ParseFloat(str, 64)
if err != nil {
return 0
}
return iv
}
val := reflect.Indirect(reflect.ValueOf(v))
switch val.Kind() {
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
return float64(val.Int())
case reflect.Uint8, reflect.Uint16, reflect.Uint32:
return float64(val.Uint())
case reflect.Uint, reflect.Uint64:
return float64(val.Uint())
case reflect.Float32, reflect.Float64:
return val.Float()
case reflect.Bool:
if val.Bool() == true {
return 1
}
return 0
default:
return 0
}
}
func toInt(v interface{}) int {
//It's not optimal. Bud I don't want duplicate toInt64 code.
return int(toInt64(v))
}
// toInt64 converts integer types to 64-bit integers
func toInt64(v interface{}) int64 {
if str, ok := v.(string); ok {
iv, err := strconv.ParseInt(str, 10, 64)
if err != nil {
return 0
}
return iv
}
val := reflect.Indirect(reflect.ValueOf(v))
switch val.Kind() {
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
return val.Int()
case reflect.Uint8, reflect.Uint16, reflect.Uint32:
return int64(val.Uint())
case reflect.Uint, reflect.Uint64:
tv := val.Uint()
if tv <= math.MaxInt64 {
return int64(tv)
}
// TODO: What is the sensible thing to do here?
return math.MaxInt64
case reflect.Float32, reflect.Float64:
return int64(val.Float())
case reflect.Bool:
if val.Bool() == true {
return 1
}
return 0
default:
return 0
}
}
func max(a interface{}, i ...interface{}) int64 {
aa := toInt64(a)
for _, b := range i {
bb := toInt64(b)
if bb > aa {
aa = bb
}
}
return aa
}
func min(a interface{}, i ...interface{}) int64 {
aa := toInt64(a)
for _, b := range i {
bb := toInt64(b)
if bb < aa {
aa = bb
}
}
return aa
}
func until(count int) []int {
step := 1
if count < 0 {
step = -1
}
return untilStep(0, count, step)
}
func untilStep(start, stop, step int) []int {
v := []int{}
if stop < start {
if step >= 0 {
return v
}
for i := start; i > stop; i += step {
v = append(v, i)
}
return v
}
if step <= 0 {
return v
}
for i := start; i < stop; i += step {
v = append(v, i)
}
return v
}
func floor(a interface{}) float64 {
aa := toFloat64(a)
return math.Floor(aa)
}
func ceil(a interface{}) float64 {
aa := toFloat64(a)
return math.Ceil(aa)
}
func round(a interface{}, p int, r_opt ...float64) float64 {
roundOn := .5
if len(r_opt) > 0 {
roundOn = r_opt[0]
}
val := toFloat64(a)
places := toFloat64(p)
var round float64
pow := math.Pow(10, places)
digit := pow * val
_, div := math.Modf(digit)
if div >= roundOn {
round = math.Ceil(digit)
} else {
round = math.Floor(digit)
}
return round / pow
}
// converts unix octal to decimal
func toDecimal(v interface{}) int64 {
result, err := strconv.ParseInt(fmt.Sprint(v), 8, 64)
if err != nil {
return 0
}
return result
}

View File

@ -1,35 +0,0 @@
package sprig
import (
"regexp"
)
func regexMatch(regex string, s string) bool {
match, _ := regexp.MatchString(regex, s)
return match
}
func regexFindAll(regex string, s string, n int) []string {
r := regexp.MustCompile(regex)
return r.FindAllString(s, n)
}
func regexFind(regex string, s string) string {
r := regexp.MustCompile(regex)
return r.FindString(s)
}
func regexReplaceAll(regex string, s string, repl string) string {
r := regexp.MustCompile(regex)
return r.ReplaceAllString(s, repl)
}
func regexReplaceAllLiteral(regex string, s string, repl string) string {
r := regexp.MustCompile(regex)
return r.ReplaceAllLiteralString(s, repl)
}
func regexSplit(regex string, s string, n int) []string {
r := regexp.MustCompile(regex)
return r.Split(s, n)
}

View File

@ -1,5 +1,93 @@
# Changelog
## Release 3.2.1 (2021-02-04)
### Changed
- Upgraded `Masterminds/goutils` to `v1.1.1`. see the [Security Advisory](https://github.com/Masterminds/goutils/security/advisories/GHSA-xg2h-wx96-xgxr)
## Release 3.2.0 (2020-12-14)
### Added
- #211: Added randInt function (thanks @kochurovro)
- #223: Added fromJson and mustFromJson functions (thanks @mholt)
- #242: Added a bcrypt function (thanks @robbiet480)
- #253: Added randBytes function (thanks @MikaelSmith)
- #254: Added dig function for dicts (thanks @nyarly)
- #257: Added regexQuoteMeta for quoting regex metadata (thanks @rheaton)
- #261: Added filepath functions osBase, osDir, osExt, osClean, osIsAbs (thanks @zugl)
- #268: Added and and all functions for testing conditions (thanks @phuslu)
- #181: Added float64 arithmetic addf, add1f, subf, divf, mulf, maxf, and minf
(thanks @andrewmostello)
- #265: Added chunk function to split array into smaller arrays (thanks @karelbilek)
- #270: Extend certificate functions to handle non-RSA keys + add support for
ed25519 keys (thanks @misberner)
### Changed
- Removed testing and support for Go 1.12. ed25519 support requires Go 1.13 or newer
- Using semver 3.1.1 and mergo 0.3.11
### Fixed
- #249: Fix htmlDateInZone example (thanks @spawnia)
NOTE: The dependency github.com/imdario/mergo reverted the breaking change in
0.3.9 via 0.3.10 release.
## Release 3.1.0 (2020-04-16)
NOTE: The dependency github.com/imdario/mergo made a behavior change in 0.3.9
that impacts sprig functionality. Do not use sprig with a version newer than 0.3.8.
### Added
- #225: Added support for generating htpasswd hash (thanks @rustycl0ck)
- #224: Added duration filter (thanks @frebib)
- #205: Added `seq` function (thanks @thadc23)
### Changed
- #203: Unlambda functions with correct signature (thanks @muesli)
- #236: Updated the license formatting for GitHub display purposes
- #238: Updated package dependency versions. Note, mergo not updated to 0.3.9
as it causes a breaking change for sprig. That issue is tracked at
https://github.com/imdario/mergo/issues/139
### Fixed
- #229: Fix `seq` example in docs (thanks @kalmant)
## Release 3.0.2 (2019-12-13)
### Fixed
- #220: Updating to semver v3.0.3 to fix issue with <= ranges
- #218: fix typo elyptical->elliptic in ecdsa key description (thanks @laverya)
## Release 3.0.1 (2019-12-08)
### Fixed
- #212: Updated semver fixing broken constraint checking with ^0.0
## Release 3.0.0 (2019-10-02)
### Added
- #187: Added durationRound function (thanks @yjp20)
- #189: Added numerous template functions that return errors rather than panic (thanks @nrvnrvn)
- #193: Added toRawJson support (thanks @Dean-Coakley)
- #197: Added get support to dicts (thanks @Dean-Coakley)
### Changed
- #186: Moving dependency management to Go modules
- #186: Updated semver to v3. This has changes in the way ^ is handled
- #194: Updated documentation on merging and how it copies. Added example using deepCopy
- #196: trunc now supports negative values (thanks @Dean-Coakley)
## Release 2.22.0 (2019-10-02)
### Added

View File

@ -1,5 +1,4 @@
Sprig
Copyright (C) 2013 Masterminds
Copyright (C) 2013-2020 Masterminds
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

9
vendor/github.com/Masterminds/sprig/v3/Makefile generated vendored Normal file
View File

@ -0,0 +1,9 @@
.PHONY: test
test:
@echo "==> Running tests"
GO111MODULE=on go test -v
.PHONY: test-cover
test-cover:
@echo "==> Running Tests with coverage"
GO111MODULE=on go test -cover .

View File

@ -1,6 +1,9 @@
# Sprig: Template functions for Go templates
[![GoDoc](https://img.shields.io/static/v1?label=godoc&message=reference&color=blue)](https://pkg.go.dev/github.com/Masterminds/sprig/v3)
[![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/sprig)](https://goreportcard.com/report/github.com/Masterminds/sprig)
[![Stability: Sustained](https://masterminds.github.io/stability/sustained.svg)](https://masterminds.github.io/stability/sustained.html)
[![Build Status](https://travis-ci.org/Masterminds/sprig.svg?branch=master)](https://travis-ci.org/Masterminds/sprig)
[![](https://github.com/Masterminds/sprig/workflows/Tests/badge.svg)](https://github.com/Masterminds/sprig/actions)
The Go language comes with a [built-in template
language](http://golang.org/pkg/text/template/), but not
@ -11,6 +14,26 @@ It is inspired by the template functions found in
[Twig](http://twig.sensiolabs.org/documentation) and in various
JavaScript libraries, such as [underscore.js](http://underscorejs.org/).
## IMPORTANT NOTES
Sprig leverages [mergo](https://github.com/imdario/mergo) to handle merges. In
its v0.3.9 release there was a behavior change that impacts merging template
functions in sprig. It is currently recommended to use v0.3.8 of that package.
Using v0.3.9 will cause sprig tests to fail. The issue in mergo is tracked at
https://github.com/imdario/mergo/issues/139.
## Package Versions
There are two active major versions of the `sprig` package.
* v3 is currently stable release series on the `master` branch. The Go API should
remain compatible with v2, the current stable version. Behavior change behind
some functions is the reason for the new major version.
* v2 is the previous stable release series. It has been more than three years since
the initial release of v2. You can read the documentation and see the code
on the [release-2](https://github.com/Masterminds/sprig/tree/release-2) branch.
Bug fixes to this major version will continue for some time.
## Usage
**Template developers**: Please use Sprig's [function documentation](http://masterminds.github.io/sprig/) for

View File

@ -2,10 +2,12 @@ package sprig
import (
"bytes"
"crypto"
"crypto/aes"
"crypto/cipher"
"crypto/dsa"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
"crypto/hmac"
"crypto/rand"
@ -21,13 +23,16 @@ import (
"encoding/pem"
"errors"
"fmt"
"io"
"hash/adler32"
"io"
"math/big"
"net"
"time"
"strings"
"github.com/google/uuid"
bcrypt_lib "golang.org/x/crypto/bcrypt"
"golang.org/x/crypto/scrypt"
)
@ -46,14 +51,38 @@ func adler32sum(input string) string {
return fmt.Sprintf("%d", hash)
}
// uuidv4 provides a safe and secure UUID v4 implementation
func uuidv4() string {
return fmt.Sprintf("%s", uuid.New())
func bcrypt(input string) string {
hash, err := bcrypt_lib.GenerateFromPassword([]byte(input), bcrypt_lib.DefaultCost)
if err != nil {
return fmt.Sprintf("failed to encrypt string with bcrypt: %s", err)
}
return string(hash)
}
var master_password_seed = "com.lyndir.masterpassword"
func htpasswd(username string, password string) string {
if strings.Contains(username, ":") {
return fmt.Sprintf("invalid username: %s", username)
}
return fmt.Sprintf("%s:%s", username, bcrypt(password))
}
var password_type_templates = map[string][][]byte{
func randBytes(count int) (string, error) {
buf := make([]byte, count)
if _, err := rand.Read(buf); err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(buf), nil
}
// uuidv4 provides a safe and secure UUID v4 implementation
func uuidv4() string {
return uuid.New().String()
}
var masterPasswordSeed = "com.lyndir.masterpassword"
var passwordTypeTemplates = map[string][][]byte{
"maximum": {[]byte("anoxxxxxxxxxxxxxxxxx"), []byte("axxxxxxxxxxxxxxxxxno")},
"long": {[]byte("CvcvnoCvcvCvcv"), []byte("CvcvCvcvnoCvcv"), []byte("CvcvCvcvCvcvno"), []byte("CvccnoCvcvCvcv"), []byte("CvccCvcvnoCvcv"),
[]byte("CvccCvcvCvcvno"), []byte("CvcvnoCvccCvcv"), []byte("CvcvCvccnoCvcv"), []byte("CvcvCvccCvcvno"), []byte("CvcvnoCvcvCvcc"),
@ -66,7 +95,7 @@ var password_type_templates = map[string][][]byte{
"pin": {[]byte("nnnn")},
}
var template_characters = map[byte]string{
var templateCharacters = map[byte]string{
'V': "AEIOU",
'C': "BCDFGHJKLMNPQRSTVWXYZ",
'v': "aeiou",
@ -78,14 +107,14 @@ var template_characters = map[byte]string{
'x': "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()",
}
func derivePassword(counter uint32, password_type, password, user, site string) string {
var templates = password_type_templates[password_type]
func derivePassword(counter uint32, passwordType, password, user, site string) string {
var templates = passwordTypeTemplates[passwordType]
if templates == nil {
return fmt.Sprintf("cannot find password template %s", password_type)
return fmt.Sprintf("cannot find password template %s", passwordType)
}
var buffer bytes.Buffer
buffer.WriteString(master_password_seed)
buffer.WriteString(masterPasswordSeed)
binary.Write(&buffer, binary.BigEndian, uint32(len(user)))
buffer.WriteString(user)
@ -95,7 +124,7 @@ func derivePassword(counter uint32, password_type, password, user, site string)
return fmt.Sprintf("failed to derive password: %s", err)
}
buffer.Truncate(len(master_password_seed))
buffer.Truncate(len(masterPasswordSeed))
binary.Write(&buffer, binary.BigEndian, uint32(len(site)))
buffer.WriteString(site)
binary.Write(&buffer, binary.BigEndian, counter)
@ -107,9 +136,9 @@ func derivePassword(counter uint32, password_type, password, user, site string)
buffer.Truncate(0)
for i, element := range temp {
pass_chars := template_characters[element]
pass_char := pass_chars[int(seed[i+1])%len(pass_chars)]
buffer.WriteByte(pass_char)
passChars := templateCharacters[element]
passChar := passChars[int(seed[i+1])%len(passChars)]
buffer.WriteByte(passChar)
}
return buffer.String()
@ -133,6 +162,8 @@ func generatePrivateKey(typ string) string {
case "ecdsa":
// again, good enough for government work
priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
case "ed25519":
_, priv, err = ed25519.GenerateKey(rand.Reader)
default:
return "Unknown type " + typ
}
@ -143,6 +174,8 @@ func generatePrivateKey(typ string) string {
return string(pem.EncodeToMemory(pemBlockForKey(priv)))
}
// DSAKeyFormat stores the format for DSA keys.
// Used by pemBlockForKey
type DSAKeyFormat struct {
Version int
P, Q, G, Y, X *big.Int
@ -163,7 +196,73 @@ func pemBlockForKey(priv interface{}) *pem.Block {
b, _ := x509.MarshalECPrivateKey(k)
return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
default:
return nil
// attempt PKCS#8 format for all other keys
b, err := x509.MarshalPKCS8PrivateKey(k)
if err != nil {
return nil
}
return &pem.Block{Type: "PRIVATE KEY", Bytes: b}
}
}
func parsePrivateKeyPEM(pemBlock string) (crypto.PrivateKey, error) {
block, _ := pem.Decode([]byte(pemBlock))
if block == nil {
return nil, errors.New("no PEM data in input")
}
if block.Type == "PRIVATE KEY" {
priv, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("decoding PEM as PKCS#8: %s", err)
}
return priv, nil
} else if !strings.HasSuffix(block.Type, " PRIVATE KEY") {
return nil, fmt.Errorf("no private key data in PEM block of type %s", block.Type)
}
switch block.Type[:len(block.Type)-12] { // strip " PRIVATE KEY"
case "RSA":
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("parsing RSA private key from PEM: %s", err)
}
return priv, nil
case "EC":
priv, err := x509.ParseECPrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("parsing EC private key from PEM: %s", err)
}
return priv, nil
case "DSA":
var k DSAKeyFormat
_, err := asn1.Unmarshal(block.Bytes, &k)
if err != nil {
return nil, fmt.Errorf("parsing DSA private key from PEM: %s", err)
}
priv := &dsa.PrivateKey{
PublicKey: dsa.PublicKey{
Parameters: dsa.Parameters{
P: k.P, Q: k.Q, G: k.G,
},
Y: k.Y,
},
X: k.X,
}
return priv, nil
default:
return nil, fmt.Errorf("invalid private key type %s", block.Type)
}
}
func getPublicKey(priv crypto.PrivateKey) (crypto.PublicKey, error) {
switch k := priv.(type) {
case interface{ Public() crypto.PublicKey }:
return k.Public(), nil
case *dsa.PrivateKey:
return &k.PublicKey, nil
default:
return nil, fmt.Errorf("unable to get public key for type %T", priv)
}
}
@ -197,14 +296,10 @@ func buildCustomCertificate(b64cert string, b64key string) (certificate, error)
)
}
decodedKey, _ := pem.Decode(key)
if decodedKey == nil {
return crt, errors.New("unable to decode key")
}
_, err = x509.ParsePKCS1PrivateKey(decodedKey.Bytes)
_, err = parsePrivateKeyPEM(string(key))
if err != nil {
return crt, fmt.Errorf(
"error parsing prive key: decodedKey.Bytes: %s",
"error parsing private key: %s",
err,
)
}
@ -218,6 +313,31 @@ func buildCustomCertificate(b64cert string, b64key string) (certificate, error)
func generateCertificateAuthority(
cn string,
daysValid int,
) (certificate, error) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return certificate{}, fmt.Errorf("error generating rsa key: %s", err)
}
return generateCertificateAuthorityWithKeyInternal(cn, daysValid, priv)
}
func generateCertificateAuthorityWithPEMKey(
cn string,
daysValid int,
privPEM string,
) (certificate, error) {
priv, err := parsePrivateKeyPEM(privPEM)
if err != nil {
return certificate{}, fmt.Errorf("parsing private key: %s", err)
}
return generateCertificateAuthorityWithKeyInternal(cn, daysValid, priv)
}
func generateCertificateAuthorityWithKeyInternal(
cn string,
daysValid int,
priv crypto.PrivateKey,
) (certificate, error) {
ca := certificate{}
@ -231,17 +351,9 @@ func generateCertificateAuthority(
x509.KeyUsageCertSign
template.IsCA = true
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return ca, fmt.Errorf("error generating rsa key: %s", err)
}
ca.Cert, ca.Key, err = getCertAndKey(template, priv, template, priv)
if err != nil {
return ca, err
}
return ca, nil
return ca, err
}
func generateSelfSignedCertificate(
@ -249,6 +361,34 @@ func generateSelfSignedCertificate(
ips []interface{},
alternateDNS []interface{},
daysValid int,
) (certificate, error) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return certificate{}, fmt.Errorf("error generating rsa key: %s", err)
}
return generateSelfSignedCertificateWithKeyInternal(cn, ips, alternateDNS, daysValid, priv)
}
func generateSelfSignedCertificateWithPEMKey(
cn string,
ips []interface{},
alternateDNS []interface{},
daysValid int,
privPEM string,
) (certificate, error) {
priv, err := parsePrivateKeyPEM(privPEM)
if err != nil {
return certificate{}, fmt.Errorf("parsing private key: %s", err)
}
return generateSelfSignedCertificateWithKeyInternal(cn, ips, alternateDNS, daysValid, priv)
}
func generateSelfSignedCertificateWithKeyInternal(
cn string,
ips []interface{},
alternateDNS []interface{},
daysValid int,
priv crypto.PrivateKey,
) (certificate, error) {
cert := certificate{}
@ -257,17 +397,9 @@ func generateSelfSignedCertificate(
return cert, err
}
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return cert, fmt.Errorf("error generating rsa key: %s", err)
}
cert.Cert, cert.Key, err = getCertAndKey(template, priv, template, priv)
if err != nil {
return cert, err
}
return cert, nil
return cert, err
}
func generateSignedCertificate(
@ -276,6 +408,36 @@ func generateSignedCertificate(
alternateDNS []interface{},
daysValid int,
ca certificate,
) (certificate, error) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return certificate{}, fmt.Errorf("error generating rsa key: %s", err)
}
return generateSignedCertificateWithKeyInternal(cn, ips, alternateDNS, daysValid, ca, priv)
}
func generateSignedCertificateWithPEMKey(
cn string,
ips []interface{},
alternateDNS []interface{},
daysValid int,
ca certificate,
privPEM string,
) (certificate, error) {
priv, err := parsePrivateKeyPEM(privPEM)
if err != nil {
return certificate{}, fmt.Errorf("parsing private key: %s", err)
}
return generateSignedCertificateWithKeyInternal(cn, ips, alternateDNS, daysValid, ca, priv)
}
func generateSignedCertificateWithKeyInternal(
cn string,
ips []interface{},
alternateDNS []interface{},
daysValid int,
ca certificate,
priv crypto.PrivateKey,
) (certificate, error) {
cert := certificate{}
@ -290,14 +452,10 @@ func generateSignedCertificate(
err,
)
}
decodedSignerKey, _ := pem.Decode([]byte(ca.Key))
if decodedSignerKey == nil {
return cert, errors.New("unable to decode key")
}
signerKey, err := x509.ParsePKCS1PrivateKey(decodedSignerKey.Bytes)
signerKey, err := parsePrivateKeyPEM(ca.Key)
if err != nil {
return cert, fmt.Errorf(
"error parsing prive key: decodedSignerKey.Bytes: %s",
"error parsing private key: %s",
err,
)
}
@ -307,35 +465,31 @@ func generateSignedCertificate(
return cert, err
}
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return cert, fmt.Errorf("error generating rsa key: %s", err)
}
cert.Cert, cert.Key, err = getCertAndKey(
template,
priv,
signerCert,
signerKey,
)
if err != nil {
return cert, err
}
return cert, nil
return cert, err
}
func getCertAndKey(
template *x509.Certificate,
signeeKey *rsa.PrivateKey,
signeeKey crypto.PrivateKey,
parent *x509.Certificate,
signingKey *rsa.PrivateKey,
signingKey crypto.PrivateKey,
) (string, string, error) {
signeePubKey, err := getPublicKey(signeeKey)
if err != nil {
return "", "", fmt.Errorf("error retrieving public key from signee key: %s", err)
}
derBytes, err := x509.CreateCertificate(
rand.Reader,
template,
parent,
&signeeKey.PublicKey,
signeePubKey,
signingKey,
)
if err != nil {
@ -353,15 +507,12 @@ func getCertAndKey(
keyBuffer := bytes.Buffer{}
if err := pem.Encode(
&keyBuffer,
&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(signeeKey),
},
pemBlockForKey(signeeKey),
); err != nil {
return "", "", fmt.Errorf("error pem-encoding key: %s", err)
}
return string(certBuffer.Bytes()), string(keyBuffer.Bytes()), nil
return certBuffer.String(), keyBuffer.String(), nil
}
func getBaseCertTemplate(

View File

@ -55,6 +55,14 @@ func dateModify(fmt string, date time.Time) time.Time {
return date.Add(d)
}
func mustDateModify(fmt string, date time.Time) (time.Time, error) {
d, err := time.ParseDuration(fmt)
if err != nil {
return time.Time{}, err
}
return date.Add(d), nil
}
func dateAgo(date interface{}) string {
var t time.Time
@ -73,11 +81,72 @@ func dateAgo(date interface{}) string {
return duration.String()
}
func duration(sec interface{}) string {
var n int64
switch value := sec.(type) {
default:
n = 0
case string:
n, _ = strconv.ParseInt(value, 10, 64)
case int64:
n = value
}
return (time.Duration(n) * time.Second).String()
}
func durationRound(duration interface{}) string {
var d time.Duration
switch duration := duration.(type) {
default:
d = 0
case string:
d, _ = time.ParseDuration(duration)
case int64:
d = time.Duration(duration)
case time.Time:
d = time.Since(duration)
}
u := uint64(d)
neg := d < 0
if neg {
u = -u
}
var (
year = uint64(time.Hour) * 24 * 365
month = uint64(time.Hour) * 24 * 30
day = uint64(time.Hour) * 24
hour = uint64(time.Hour)
minute = uint64(time.Minute)
second = uint64(time.Second)
)
switch {
case u > year:
return strconv.FormatUint(u/year, 10) + "y"
case u > month:
return strconv.FormatUint(u/month, 10) + "mo"
case u > day:
return strconv.FormatUint(u/day, 10) + "d"
case u > hour:
return strconv.FormatUint(u/hour, 10) + "h"
case u > minute:
return strconv.FormatUint(u/minute, 10) + "m"
case u > second:
return strconv.FormatUint(u/second, 10) + "s"
}
return "0s"
}
func toDate(fmt, str string) time.Time {
t, _ := time.ParseInLocation(fmt, str, time.Local)
return t
}
func mustToDate(fmt, str string) (time.Time, error) {
return time.ParseInLocation(fmt, str, time.Local)
}
func unixEpoch(date time.Time) string {
return strconv.FormatInt(date.Unix(), 10)
}

View File

@ -1,10 +1,18 @@
package sprig
import (
"bytes"
"encoding/json"
"math/rand"
"reflect"
"strings"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
// dfault checks whether `given` is set, and returns default if not set.
//
// This returns `d` if `given` appears not to be set, and `given` otherwise.
@ -37,7 +45,7 @@ func empty(given interface{}) bool {
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
return g.Len() == 0
case reflect.Bool:
return g.Bool() == false
return !g.Bool()
case reflect.Complex64, reflect.Complex128:
return g.Complex() == 0
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
@ -61,18 +69,90 @@ func coalesce(v ...interface{}) interface{} {
return nil
}
// all returns true if empty(x) is false for all values x in the list.
// If the list is empty, return true.
func all(v ...interface{}) bool {
for _, val := range v {
if empty(val) {
return false
}
}
return true
}
// any returns true if empty(x) is false for any x in the list.
// If the list is empty, return false.
func any(v ...interface{}) bool {
for _, val := range v {
if !empty(val) {
return true
}
}
return false
}
// fromJson decodes JSON into a structured value, ignoring errors.
func fromJson(v string) interface{} {
output, _ := mustFromJson(v)
return output
}
// mustFromJson decodes JSON into a structured value, returning errors.
func mustFromJson(v string) (interface{}, error) {
var output interface{}
err := json.Unmarshal([]byte(v), &output)
return output, err
}
// toJson encodes an item into a JSON string
func toJson(v interface{}) string {
output, _ := json.Marshal(v)
return string(output)
}
func mustToJson(v interface{}) (string, error) {
output, err := json.Marshal(v)
if err != nil {
return "", err
}
return string(output), nil
}
// toPrettyJson encodes an item into a pretty (indented) JSON string
func toPrettyJson(v interface{}) string {
output, _ := json.MarshalIndent(v, "", " ")
return string(output)
}
func mustToPrettyJson(v interface{}) (string, error) {
output, err := json.MarshalIndent(v, "", " ")
if err != nil {
return "", err
}
return string(output), nil
}
// toRawJson encodes an item into a JSON string with no escaping of HTML characters.
func toRawJson(v interface{}) string {
output, err := mustToRawJson(v)
if err != nil {
panic(err)
}
return string(output)
}
// mustToRawJson encodes an item into a JSON string with no escaping of HTML characters.
func mustToRawJson(v interface{}) (string, error) {
buf := new(bytes.Buffer)
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
err := enc.Encode(&v)
if err != nil {
return "", err
}
return strings.TrimSuffix(buf.String(), "\n"), nil
}
// ternary returns the first value if the last value is true, otherwise returns the second value.
func ternary(vt interface{}, vf interface{}, v bool) interface{} {
if v {

View File

@ -5,6 +5,13 @@ import (
"github.com/mitchellh/copystructure"
)
func get(d map[string]interface{}, key string) interface{} {
if val, ok := d[key]; ok {
return val
}
return ""
}
func set(d map[string]interface{}, key string, value interface{}) map[string]interface{} {
d[key] = value
return d
@ -90,6 +97,15 @@ func merge(dst map[string]interface{}, srcs ...map[string]interface{}) interface
return dst
}
func mustMerge(dst map[string]interface{}, srcs ...map[string]interface{}) (interface{}, error) {
for _, src := range srcs {
if err := mergo.Merge(&dst, src); err != nil {
return nil, err
}
}
return dst, nil
}
func mergeOverwrite(dst map[string]interface{}, srcs ...map[string]interface{}) interface{} {
for _, src := range srcs {
if err := mergo.MergeWithOverwrite(&dst, src); err != nil {
@ -100,6 +116,15 @@ func mergeOverwrite(dst map[string]interface{}, srcs ...map[string]interface{})
return dst
}
func mustMergeOverwrite(dst map[string]interface{}, srcs ...map[string]interface{}) (interface{}, error) {
for _, src := range srcs {
if err := mergo.MergeWithOverwrite(&dst, src); err != nil {
return nil, err
}
}
return dst, nil
}
func values(dict map[string]interface{}) []interface{} {
values := []interface{}{}
for _, value := range dict {
@ -110,10 +135,40 @@ func values(dict map[string]interface{}) []interface{} {
}
func deepCopy(i interface{}) interface{} {
c, err := copystructure.Copy(i)
c, err := mustDeepCopy(i)
if err != nil {
panic("deepCopy error: " + err.Error())
}
return c
}
func mustDeepCopy(i interface{}) (interface{}, error) {
return copystructure.Copy(i)
}
func dig(ps ...interface{}) (interface{}, error) {
if len(ps) < 3 {
panic("dig needs at least three arguments")
}
dict := ps[len(ps)-1].(map[string]interface{})
def := ps[len(ps)-2]
ks := make([]string, len(ps)-2)
for i := 0; i < len(ks); i++ {
ks[i] = ps[i].(string)
}
return digFromDict(dict, def, ks)
}
func digFromDict(dict map[string]interface{}, d interface{}, ks []string) (interface{}, error) {
k, ns := ks[0], ks[1:len(ks)]
step, has := dict[k]
if !has {
return d, nil
}
if len(ns) == 0 {
return step, nil
}
return digFromDict(step.(map[string]interface{}), d, ns)
}

View File

@ -1,5 +1,5 @@
/*
Sprig: Template functions for Go.
Package sprig provides template functions for Go.
This package contains a number of utility functions for working with data
inside of Go `html/template` and `text/template` files.

View File

@ -3,8 +3,10 @@ package sprig
import (
"errors"
"html/template"
"math/rand"
"os"
"path"
"path/filepath"
"reflect"
"strconv"
"strings"
@ -13,9 +15,10 @@ import (
util "github.com/Masterminds/goutils"
"github.com/huandu/xstrings"
"github.com/shopspring/decimal"
)
// Produce the function map.
// FuncMap produces the function map.
//
// Use this to pass the functions into the template engine:
//
@ -63,7 +66,7 @@ func GenericFuncMap() map[string]interface{} {
}
// These functions are not guaranteed to evaluate to the same result for given input, because they
// refer to the environemnt or global state.
// refer to the environment or global state.
var nonhermeticFunctions = []string{
// Date functions
"date",
@ -80,6 +83,7 @@ var nonhermeticFunctions = []string{
"randAlpha",
"randAscii",
"randNumeric",
"randBytes",
"uuidv4",
// OS
@ -94,17 +98,22 @@ var genericMap = map[string]interface{}{
"hello": func() string { return "Hello!" },
// Date functions
"date": date,
"date_in_zone": dateInZone,
"date_modify": dateModify,
"now": func() time.Time { return time.Now() },
"htmlDate": htmlDate,
"htmlDateInZone": htmlDateInZone,
"dateInZone": dateInZone,
"dateModify": dateModify,
"ago": dateAgo,
"toDate": toDate,
"unixEpoch": unixEpoch,
"ago": dateAgo,
"date": date,
"date_in_zone": dateInZone,
"date_modify": dateModify,
"dateInZone": dateInZone,
"dateModify": dateModify,
"duration": duration,
"durationRound": durationRound,
"htmlDate": htmlDate,
"htmlDateInZone": htmlDateInZone,
"must_date_modify": mustDateModify,
"mustDateModify": mustDateModify,
"mustToDate": mustToDate,
"now": time.Now,
"toDate": toDate,
"unixEpoch": unixEpoch,
// Strings
"abbrev": abbrev,
@ -158,6 +167,7 @@ var genericMap = map[string]interface{}{
"int64": toInt64,
"int": toInt,
"float64": toFloat64,
"seq": seq,
"toDecimal": toDecimal,
//"gt": func(a, b int) bool {return a > b},
@ -194,9 +204,28 @@ var genericMap = map[string]interface{}{
}
return val
},
"randInt": func(min, max int) int { return rand.Intn(max-min) + min },
"add1f": func(i interface{}) float64 {
return execDecimalOp(i, []interface{}{1}, func(d1, d2 decimal.Decimal) decimal.Decimal { return d1.Add(d2) })
},
"addf": func(i ...interface{}) float64 {
a := interface{}(float64(0))
return execDecimalOp(a, i, func(d1, d2 decimal.Decimal) decimal.Decimal { return d1.Add(d2) })
},
"subf": func(a interface{}, v ...interface{}) float64 {
return execDecimalOp(a, v, func(d1, d2 decimal.Decimal) decimal.Decimal { return d1.Sub(d2) })
},
"divf": func(a interface{}, v ...interface{}) float64 {
return execDecimalOp(a, v, func(d1, d2 decimal.Decimal) decimal.Decimal { return d1.Div(d2) })
},
"mulf": func(a interface{}, v ...interface{}) float64 {
return execDecimalOp(a, v, func(d1, d2 decimal.Decimal) decimal.Decimal { return d1.Mul(d2) })
},
"biggest": max,
"max": max,
"min": min,
"maxf": maxf,
"minf": minf,
"ceil": ceil,
"floor": floor,
"round": round,
@ -207,14 +236,24 @@ var genericMap = map[string]interface{}{
"sortAlpha": sortAlpha,
// Defaults
"default": dfault,
"empty": empty,
"coalesce": coalesce,
"compact": compact,
"deepCopy": deepCopy,
"toJson": toJson,
"toPrettyJson": toPrettyJson,
"ternary": ternary,
"default": dfault,
"empty": empty,
"coalesce": coalesce,
"all": all,
"any": any,
"compact": compact,
"mustCompact": mustCompact,
"fromJson": fromJson,
"toJson": toJson,
"toPrettyJson": toPrettyJson,
"toRawJson": toRawJson,
"mustFromJson": mustFromJson,
"mustToJson": mustToJson,
"mustToPrettyJson": mustToPrettyJson,
"mustToRawJson": mustToRawJson,
"ternary": ternary,
"deepCopy": deepCopy,
"mustDeepCopy": mustDeepCopy,
// Reflection
"typeOf": typeOf,
@ -225,19 +264,26 @@ var genericMap = map[string]interface{}{
"deepEqual": reflect.DeepEqual,
// OS:
"env": func(s string) string { return os.Getenv(s) },
"expandenv": func(s string) string { return os.ExpandEnv(s) },
"env": os.Getenv,
"expandenv": os.ExpandEnv,
// Network:
"getHostByName": getHostByName,
// File Paths:
// Paths:
"base": path.Base,
"dir": path.Dir,
"clean": path.Clean,
"ext": path.Ext,
"isAbs": path.IsAbs,
// Filepaths:
"osBase": filepath.Base,
"osClean": filepath.Clean,
"osDir": filepath.Dir,
"osExt": filepath.Ext,
"osIsAbs": filepath.IsAbs,
// Encoding:
"b64enc": base64encode,
"b64dec": base64decode,
@ -245,42 +291,65 @@ var genericMap = map[string]interface{}{
"b32dec": base32decode,
// Data Structures:
"tuple": list, // FIXME: with the addition of append/prepend these are no longer immutable.
"list": list,
"dict": dict,
"set": set,
"unset": unset,
"hasKey": hasKey,
"pluck": pluck,
"keys": keys,
"pick": pick,
"omit": omit,
"merge": merge,
"mergeOverwrite": mergeOverwrite,
"values": values,
"tuple": list, // FIXME: with the addition of append/prepend these are no longer immutable.
"list": list,
"dict": dict,
"get": get,
"set": set,
"unset": unset,
"hasKey": hasKey,
"pluck": pluck,
"keys": keys,
"pick": pick,
"omit": omit,
"merge": merge,
"mergeOverwrite": mergeOverwrite,
"mustMerge": mustMerge,
"mustMergeOverwrite": mustMergeOverwrite,
"values": values,
"append": push, "push": push,
"prepend": prepend,
"first": first,
"rest": rest,
"last": last,
"initial": initial,
"reverse": reverse,
"uniq": uniq,
"without": without,
"has": has,
"slice": slice,
"concat": concat,
"mustAppend": mustPush, "mustPush": mustPush,
"prepend": prepend,
"mustPrepend": mustPrepend,
"first": first,
"mustFirst": mustFirst,
"rest": rest,
"mustRest": mustRest,
"last": last,
"mustLast": mustLast,
"initial": initial,
"mustInitial": mustInitial,
"reverse": reverse,
"mustReverse": mustReverse,
"uniq": uniq,
"mustUniq": mustUniq,
"without": without,
"mustWithout": mustWithout,
"has": has,
"mustHas": mustHas,
"slice": slice,
"mustSlice": mustSlice,
"concat": concat,
"dig": dig,
"chunk": chunk,
"mustChunk": mustChunk,
// Crypto:
"bcrypt": bcrypt,
"htpasswd": htpasswd,
"genPrivateKey": generatePrivateKey,
"derivePassword": derivePassword,
"buildCustomCert": buildCustomCertificate,
"genCA": generateCertificateAuthority,
"genCAWithKey": generateCertificateAuthorityWithPEMKey,
"genSelfSignedCert": generateSelfSignedCertificate,
"genSelfSignedCertWithKey": generateSelfSignedCertificateWithPEMKey,
"genSignedCert": generateSignedCertificate,
"genSignedCertWithKey": generateSignedCertificateWithPEMKey,
"encryptAES": encryptAES,
"decryptAES": decryptAES,
"randBytes": randBytes,
// UUIDs:
"uuidv4": uuidv4,
@ -293,12 +362,19 @@ var genericMap = map[string]interface{}{
"fail": func(msg string) (string, error) { return "", errors.New(msg) },
// Regex
"regexMatch": regexMatch,
"regexFindAll": regexFindAll,
"regexFind": regexFind,
"regexReplaceAll": regexReplaceAll,
"regexReplaceAllLiteral": regexReplaceAllLiteral,
"regexSplit": regexSplit,
"regexMatch": regexMatch,
"mustRegexMatch": mustRegexMatch,
"regexFindAll": regexFindAll,
"mustRegexFindAll": mustRegexFindAll,
"regexFind": regexFind,
"mustRegexFind": mustRegexFind,
"regexReplaceAll": regexReplaceAll,
"mustRegexReplaceAll": mustRegexReplaceAll,
"regexReplaceAllLiteral": regexReplaceAllLiteral,
"mustRegexReplaceAllLiteral": mustRegexReplaceAllLiteral,
"regexSplit": regexSplit,
"mustRegexSplit": mustRegexSplit,
"regexQuoteMeta": regexQuoteMeta,
// URLs:
"urlParse": urlParse,

View File

@ -2,6 +2,7 @@ package sprig
import (
"fmt"
"math"
"reflect"
"sort"
)
@ -15,6 +16,15 @@ func list(v ...interface{}) []interface{} {
}
func push(list interface{}, v interface{}) []interface{} {
l, err := mustPush(list, v)
if err != nil {
panic(err)
}
return l
}
func mustPush(list interface{}, v interface{}) ([]interface{}, error) {
tp := reflect.TypeOf(list).Kind()
switch tp {
case reflect.Slice, reflect.Array:
@ -26,14 +36,23 @@ func push(list interface{}, v interface{}) []interface{} {
nl[i] = l2.Index(i).Interface()
}
return append(nl, v)
return append(nl, v), nil
default:
panic(fmt.Sprintf("Cannot push on type %s", tp))
return nil, fmt.Errorf("Cannot push on type %s", tp)
}
}
func prepend(list interface{}, v interface{}) []interface{} {
l, err := mustPrepend(list, v)
if err != nil {
panic(err)
}
return l
}
func mustPrepend(list interface{}, v interface{}) ([]interface{}, error) {
//return append([]interface{}{v}, list...)
tp := reflect.TypeOf(list).Kind()
@ -47,14 +66,67 @@ func prepend(list interface{}, v interface{}) []interface{} {
nl[i] = l2.Index(i).Interface()
}
return append([]interface{}{v}, nl...)
return append([]interface{}{v}, nl...), nil
default:
panic(fmt.Sprintf("Cannot prepend on type %s", tp))
return nil, fmt.Errorf("Cannot prepend on type %s", tp)
}
}
func chunk(size int, list interface{}) [][]interface{} {
l, err := mustChunk(size, list)
if err != nil {
panic(err)
}
return l
}
func mustChunk(size int, list interface{}) ([][]interface{}, error) {
tp := reflect.TypeOf(list).Kind()
switch tp {
case reflect.Slice, reflect.Array:
l2 := reflect.ValueOf(list)
l := l2.Len()
cs := int(math.Floor(float64(l-1)/float64(size)) + 1)
nl := make([][]interface{}, cs)
for i := 0; i < cs; i++ {
clen := size
if i == cs-1 {
clen = int(math.Floor(math.Mod(float64(l), float64(size))))
if clen == 0 {
clen = size
}
}
nl[i] = make([]interface{}, clen)
for j := 0; j < clen; j++ {
ix := i*size + j
nl[i][j] = l2.Index(ix).Interface()
}
}
return nl, nil
default:
return nil, fmt.Errorf("Cannot chunk type %s", tp)
}
}
func last(list interface{}) interface{} {
l, err := mustLast(list)
if err != nil {
panic(err)
}
return l
}
func mustLast(list interface{}) (interface{}, error) {
tp := reflect.TypeOf(list).Kind()
switch tp {
case reflect.Slice, reflect.Array:
@ -62,16 +134,25 @@ func last(list interface{}) interface{} {
l := l2.Len()
if l == 0 {
return nil
return nil, nil
}
return l2.Index(l - 1).Interface()
return l2.Index(l - 1).Interface(), nil
default:
panic(fmt.Sprintf("Cannot find last on type %s", tp))
return nil, fmt.Errorf("Cannot find last on type %s", tp)
}
}
func first(list interface{}) interface{} {
l, err := mustFirst(list)
if err != nil {
panic(err)
}
return l
}
func mustFirst(list interface{}) (interface{}, error) {
tp := reflect.TypeOf(list).Kind()
switch tp {
case reflect.Slice, reflect.Array:
@ -79,16 +160,25 @@ func first(list interface{}) interface{} {
l := l2.Len()
if l == 0 {
return nil
return nil, nil
}
return l2.Index(0).Interface()
return l2.Index(0).Interface(), nil
default:
panic(fmt.Sprintf("Cannot find first on type %s", tp))
return nil, fmt.Errorf("Cannot find first on type %s", tp)
}
}
func rest(list interface{}) []interface{} {
l, err := mustRest(list)
if err != nil {
panic(err)
}
return l
}
func mustRest(list interface{}) ([]interface{}, error) {
tp := reflect.TypeOf(list).Kind()
switch tp {
case reflect.Slice, reflect.Array:
@ -96,7 +186,7 @@ func rest(list interface{}) []interface{} {
l := l2.Len()
if l == 0 {
return nil
return nil, nil
}
nl := make([]interface{}, l-1)
@ -104,13 +194,22 @@ func rest(list interface{}) []interface{} {
nl[i-1] = l2.Index(i).Interface()
}
return nl
return nl, nil
default:
panic(fmt.Sprintf("Cannot find rest on type %s", tp))
return nil, fmt.Errorf("Cannot find rest on type %s", tp)
}
}
func initial(list interface{}) []interface{} {
l, err := mustInitial(list)
if err != nil {
panic(err)
}
return l
}
func mustInitial(list interface{}) ([]interface{}, error) {
tp := reflect.TypeOf(list).Kind()
switch tp {
case reflect.Slice, reflect.Array:
@ -118,7 +217,7 @@ func initial(list interface{}) []interface{} {
l := l2.Len()
if l == 0 {
return nil
return nil, nil
}
nl := make([]interface{}, l-1)
@ -126,9 +225,9 @@ func initial(list interface{}) []interface{} {
nl[i] = l2.Index(i).Interface()
}
return nl
return nl, nil
default:
panic(fmt.Sprintf("Cannot find initial on type %s", tp))
return nil, fmt.Errorf("Cannot find initial on type %s", tp)
}
}
@ -145,6 +244,15 @@ func sortAlpha(list interface{}) []string {
}
func reverse(v interface{}) []interface{} {
l, err := mustReverse(v)
if err != nil {
panic(err)
}
return l
}
func mustReverse(v interface{}) ([]interface{}, error) {
tp := reflect.TypeOf(v).Kind()
switch tp {
case reflect.Slice, reflect.Array:
@ -157,13 +265,22 @@ func reverse(v interface{}) []interface{} {
nl[l-i-1] = l2.Index(i).Interface()
}
return nl
return nl, nil
default:
panic(fmt.Sprintf("Cannot find reverse on type %s", tp))
return nil, fmt.Errorf("Cannot find reverse on type %s", tp)
}
}
func compact(list interface{}) []interface{} {
l, err := mustCompact(list)
if err != nil {
panic(err)
}
return l
}
func mustCompact(list interface{}) ([]interface{}, error) {
tp := reflect.TypeOf(list).Kind()
switch tp {
case reflect.Slice, reflect.Array:
@ -179,13 +296,22 @@ func compact(list interface{}) []interface{} {
}
}
return nl
return nl, nil
default:
panic(fmt.Sprintf("Cannot compact on type %s", tp))
return nil, fmt.Errorf("Cannot compact on type %s", tp)
}
}
func uniq(list interface{}) []interface{} {
l, err := mustUniq(list)
if err != nil {
panic(err)
}
return l
}
func mustUniq(list interface{}) ([]interface{}, error) {
tp := reflect.TypeOf(list).Kind()
switch tp {
case reflect.Slice, reflect.Array:
@ -201,9 +327,9 @@ func uniq(list interface{}) []interface{} {
}
}
return dest
return dest, nil
default:
panic(fmt.Sprintf("Cannot find uniq on type %s", tp))
return nil, fmt.Errorf("Cannot find uniq on type %s", tp)
}
}
@ -217,6 +343,15 @@ func inList(haystack []interface{}, needle interface{}) bool {
}
func without(list interface{}, omit ...interface{}) []interface{} {
l, err := mustWithout(list, omit...)
if err != nil {
panic(err)
}
return l
}
func mustWithout(list interface{}, omit ...interface{}) ([]interface{}, error) {
tp := reflect.TypeOf(list).Kind()
switch tp {
case reflect.Slice, reflect.Array:
@ -232,15 +367,24 @@ func without(list interface{}, omit ...interface{}) []interface{} {
}
}
return res
return res, nil
default:
panic(fmt.Sprintf("Cannot find without on type %s", tp))
return nil, fmt.Errorf("Cannot find without on type %s", tp)
}
}
func has(needle interface{}, haystack interface{}) bool {
l, err := mustHas(needle, haystack)
if err != nil {
panic(err)
}
return l
}
func mustHas(needle interface{}, haystack interface{}) (bool, error) {
if haystack == nil {
return false
return false, nil
}
tp := reflect.TypeOf(haystack).Kind()
switch tp {
@ -251,13 +395,13 @@ func has(needle interface{}, haystack interface{}) bool {
for i := 0; i < l; i++ {
item = l2.Index(i).Interface()
if reflect.DeepEqual(needle, item) {
return true
return true, nil
}
}
return false
return false, nil
default:
panic(fmt.Sprintf("Cannot find has on type %s", tp))
return false, fmt.Errorf("Cannot find has on type %s", tp)
}
}
@ -267,6 +411,15 @@ func has(needle interface{}, haystack interface{}) bool {
// slice $list 3 5 -> list[3:5]
// slice $list 3 -> list[3:5] = list[3:]
func slice(list interface{}, indices ...interface{}) interface{} {
l, err := mustSlice(list, indices...)
if err != nil {
panic(err)
}
return l
}
func mustSlice(list interface{}, indices ...interface{}) (interface{}, error) {
tp := reflect.TypeOf(list).Kind()
switch tp {
case reflect.Slice, reflect.Array:
@ -274,7 +427,7 @@ func slice(list interface{}, indices ...interface{}) interface{} {
l := l2.Len()
if l == 0 {
return nil
return nil, nil
}
var start, end int
@ -287,9 +440,9 @@ func slice(list interface{}, indices ...interface{}) interface{} {
end = toInt(indices[1])
}
return l2.Slice(start, end).Interface()
return l2.Slice(start, end).Interface(), nil
default:
panic(fmt.Sprintf("list should be type of slice or array but %s", tp))
return nil, fmt.Errorf("list should be type of slice or array but %s", tp)
}
}

View File

@ -7,6 +7,6 @@ import (
func getHostByName(name string) string {
addrs, _ := net.LookupHost(name)
//TODO: add error handing when release v3 cames out
//TODO: add error handing when release v3 comes out
return addrs[rand.Intn(len(addrs))]
}

186
vendor/github.com/Masterminds/sprig/v3/numeric.go generated vendored Normal file
View File

@ -0,0 +1,186 @@
package sprig
import (
"fmt"
"math"
"strconv"
"strings"
"github.com/spf13/cast"
"github.com/shopspring/decimal"
)
// toFloat64 converts 64-bit floats
func toFloat64(v interface{}) float64 {
return cast.ToFloat64(v)
}
func toInt(v interface{}) int {
return cast.ToInt(v)
}
// toInt64 converts integer types to 64-bit integers
func toInt64(v interface{}) int64 {
return cast.ToInt64(v)
}
func max(a interface{}, i ...interface{}) int64 {
aa := toInt64(a)
for _, b := range i {
bb := toInt64(b)
if bb > aa {
aa = bb
}
}
return aa
}
func maxf(a interface{}, i ...interface{}) float64 {
aa := toFloat64(a)
for _, b := range i {
bb := toFloat64(b)
aa = math.Max(aa, bb)
}
return aa
}
func min(a interface{}, i ...interface{}) int64 {
aa := toInt64(a)
for _, b := range i {
bb := toInt64(b)
if bb < aa {
aa = bb
}
}
return aa
}
func minf(a interface{}, i ...interface{}) float64 {
aa := toFloat64(a)
for _, b := range i {
bb := toFloat64(b)
aa = math.Min(aa, bb)
}
return aa
}
func until(count int) []int {
step := 1
if count < 0 {
step = -1
}
return untilStep(0, count, step)
}
func untilStep(start, stop, step int) []int {
v := []int{}
if stop < start {
if step >= 0 {
return v
}
for i := start; i > stop; i += step {
v = append(v, i)
}
return v
}
if step <= 0 {
return v
}
for i := start; i < stop; i += step {
v = append(v, i)
}
return v
}
func floor(a interface{}) float64 {
aa := toFloat64(a)
return math.Floor(aa)
}
func ceil(a interface{}) float64 {
aa := toFloat64(a)
return math.Ceil(aa)
}
func round(a interface{}, p int, rOpt ...float64) float64 {
roundOn := .5
if len(rOpt) > 0 {
roundOn = rOpt[0]
}
val := toFloat64(a)
places := toFloat64(p)
var round float64
pow := math.Pow(10, places)
digit := pow * val
_, div := math.Modf(digit)
if div >= roundOn {
round = math.Ceil(digit)
} else {
round = math.Floor(digit)
}
return round / pow
}
// converts unix octal to decimal
func toDecimal(v interface{}) int64 {
result, err := strconv.ParseInt(fmt.Sprint(v), 8, 64)
if err != nil {
return 0
}
return result
}
func seq(params ...int) string {
increment := 1
switch len(params) {
case 0:
return ""
case 1:
start := 1
end := params[0]
if end < start {
increment = -1
}
return intArrayToString(untilStep(start, end+increment, increment), " ")
case 3:
start := params[0]
end := params[2]
step := params[1]
if end < start {
increment = -1
if step > 0 {
return ""
}
}
return intArrayToString(untilStep(start, end+increment, step), " ")
case 2:
start := params[0]
end := params[1]
step := 1
if end < start {
step = -1
}
return intArrayToString(untilStep(start, end+step, step), " ")
default:
return ""
}
}
func intArrayToString(slice []int, delimeter string) string {
return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(slice)), delimeter), "[]")
}
// performs a float and subsequent decimal.Decimal conversion on inputs,
// and iterates through a and b executing the mathmetical operation f
func execDecimalOp(a interface{}, b []interface{}, f func(d1, d2 decimal.Decimal) decimal.Decimal) float64 {
prt := decimal.NewFromFloat(toFloat64(a))
for _, x := range b {
dx := decimal.NewFromFloat(toFloat64(x))
prt = f(prt, dx)
}
rslt, _ := prt.Float64()
return rslt
}

83
vendor/github.com/Masterminds/sprig/v3/regex.go generated vendored Normal file
View File

@ -0,0 +1,83 @@
package sprig
import (
"regexp"
)
func regexMatch(regex string, s string) bool {
match, _ := regexp.MatchString(regex, s)
return match
}
func mustRegexMatch(regex string, s string) (bool, error) {
return regexp.MatchString(regex, s)
}
func regexFindAll(regex string, s string, n int) []string {
r := regexp.MustCompile(regex)
return r.FindAllString(s, n)
}
func mustRegexFindAll(regex string, s string, n int) ([]string, error) {
r, err := regexp.Compile(regex)
if err != nil {
return []string{}, err
}
return r.FindAllString(s, n), nil
}
func regexFind(regex string, s string) string {
r := regexp.MustCompile(regex)
return r.FindString(s)
}
func mustRegexFind(regex string, s string) (string, error) {
r, err := regexp.Compile(regex)
if err != nil {
return "", err
}
return r.FindString(s), nil
}
func regexReplaceAll(regex string, s string, repl string) string {
r := regexp.MustCompile(regex)
return r.ReplaceAllString(s, repl)
}
func mustRegexReplaceAll(regex string, s string, repl string) (string, error) {
r, err := regexp.Compile(regex)
if err != nil {
return "", err
}
return r.ReplaceAllString(s, repl), nil
}
func regexReplaceAllLiteral(regex string, s string, repl string) string {
r := regexp.MustCompile(regex)
return r.ReplaceAllLiteralString(s, repl)
}
func mustRegexReplaceAllLiteral(regex string, s string, repl string) (string, error) {
r, err := regexp.Compile(regex)
if err != nil {
return "", err
}
return r.ReplaceAllLiteralString(s, repl), nil
}
func regexSplit(regex string, s string, n int) []string {
r := regexp.MustCompile(regex)
return r.Split(s, n)
}
func mustRegexSplit(regex string, s string, n int) ([]string, error) {
r, err := regexp.Compile(regex)
if err != nil {
return []string{}, err
}
return r.Split(s, n), nil
}
func regexQuoteMeta(s string) string {
return regexp.QuoteMeta(s)
}

View File

@ -1,7 +1,7 @@
package sprig
import (
sv2 "github.com/Masterminds/semver"
sv2 "github.com/Masterminds/semver/v3"
)
func semverCompare(constraint, version string) (bool, error) {

View File

@ -154,9 +154,9 @@ func strslice(v interface{}) []string {
default:
if v == nil {
return []string{}
} else {
return []string{strval(v)}
}
return []string{strval(v)}
}
}
}
@ -187,10 +187,13 @@ func strval(v interface{}) string {
}
func trunc(c int, s string) string {
if len(s) <= c {
return s
if c < 0 && len(s)+c > 0 {
return s[len(s)+c:]
}
return s[0:c]
if c >= 0 && len(s) > c {
return s[:c]
}
return s
}
func join(sep string, v interface{}) string {

View File

@ -7,7 +7,8 @@ import (
)
func dictGetOrEmpty(dict map[string]interface{}, key string) string {
value, ok := dict[key]; if !ok {
value, ok := dict[key]
if !ok {
return ""
}
tp := reflect.TypeOf(value).Kind()
@ -20,19 +21,19 @@ func dictGetOrEmpty(dict map[string]interface{}, key string) string {
// parses given URL to return dict object
func urlParse(v string) map[string]interface{} {
dict := map[string]interface{}{}
parsedUrl, err := url.Parse(v)
parsedURL, err := url.Parse(v)
if err != nil {
panic(fmt.Sprintf("unable to parse url: %s", err))
}
dict["scheme"] = parsedUrl.Scheme
dict["host"] = parsedUrl.Host
dict["hostname"] = parsedUrl.Hostname()
dict["path"] = parsedUrl.Path
dict["query"] = parsedUrl.RawQuery
dict["opaque"] = parsedUrl.Opaque
dict["fragment"] = parsedUrl.Fragment
if parsedUrl.User != nil {
dict["userinfo"] = parsedUrl.User.String()
dict["scheme"] = parsedURL.Scheme
dict["host"] = parsedURL.Host
dict["hostname"] = parsedURL.Hostname()
dict["path"] = parsedURL.Path
dict["query"] = parsedURL.RawQuery
dict["opaque"] = parsedURL.Opaque
dict["fragment"] = parsedURL.Fragment
if parsedURL.User != nil {
dict["userinfo"] = parsedURL.User.String()
} else {
dict["userinfo"] = ""
}
@ -42,25 +43,24 @@ func urlParse(v string) map[string]interface{} {
// join given dict to URL string
func urlJoin(d map[string]interface{}) string {
resUrl := url.URL{
resURL := url.URL{
Scheme: dictGetOrEmpty(d, "scheme"),
Host: dictGetOrEmpty(d, "host"),
Path: dictGetOrEmpty(d, "path"),
RawQuery: dictGetOrEmpty(d, "query"),
Opaque: dictGetOrEmpty(d, "opaque"),
Fragment: dictGetOrEmpty(d, "fragment"),
}
userinfo := dictGetOrEmpty(d, "userinfo")
var user *url.Userinfo = nil
var user *url.Userinfo
if userinfo != "" {
tempUrl, err := url.Parse(fmt.Sprintf("proto://%s@host", userinfo))
tempURL, err := url.Parse(fmt.Sprintf("proto://%s@host", userinfo))
if err != nil {
panic(fmt.Sprintf("unable to parse userinfo in dict: %s", err))
}
user = tempUrl.User
user = tempURL.User
}
resUrl.User = user
return resUrl.String()
resURL.User = user
return resURL.String()
}

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

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

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

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,33 +4,25 @@
// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
// very similar to PEM except that it has an additional CRC checksum.
//
// Deprecated: this package is unmaintained except for security fixes. New
// applications should consider a more focused, modern alternative to OpenPGP
// for their specific task. If you are required to interoperate with OpenPGP
// systems and need a maintained package, consider a community fork.
// See https://golang.org/issue/44226.
package armor // import "golang.org/x/crypto/openpgp/armor"
package armor // import "github.com/ProtonMail/go-crypto/openpgp/armor"
import (
"bufio"
"bytes"
"encoding/base64"
"golang.org/x/crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"io"
)
// A Block represents an OpenPGP armored structure.
//
// The encoded form is:
// -----BEGIN Type-----
// Headers
//
// -----BEGIN Type-----
// Headers
//
// base64-encoded Bytes
// '=' base64 encoded checksum
// -----END Type-----
//
// base64-encoded Bytes
// '=' base64 encoded checksum
// -----END Type-----
// where Headers is a possibly empty sequence of Key: Value lines.
//
// Since the armored data can be very large, this package presents a streaming

View File

@ -96,8 +96,7 @@ func (l *lineBreaker) Close() (err error) {
// trailer.
//
// It's built into a stack of io.Writers:
//
// encoding -> base64 encoder -> lineBreaker -> out
// encoding -> base64 encoder -> lineBreaker -> out
type encoding struct {
out io.Writer
breaker *lineBreaker

View File

@ -4,7 +4,10 @@
package openpgp
import "hash"
import (
"hash"
"io"
)
// NewCanonicalTextHash reformats text written to it into the canonical
// form and then applies the hash h. See RFC 4880, section 5.2.1.
@ -19,28 +22,31 @@ type canonicalTextHash struct {
var newline = []byte{'\r', '\n'}
func (cth *canonicalTextHash) Write(buf []byte) (int, error) {
func writeCanonical(cw io.Writer, buf []byte, s *int) (int, error) {
start := 0
for i, c := range buf {
switch cth.s {
switch *s {
case 0:
if c == '\r' {
cth.s = 1
*s = 1
} else if c == '\n' {
cth.h.Write(buf[start:i])
cth.h.Write(newline)
cw.Write(buf[start:i])
cw.Write(newline)
start = i + 1
}
case 1:
cth.s = 0
*s = 0
}
}
cth.h.Write(buf[start:])
cw.Write(buf[start:])
return len(buf), nil
}
func (cth *canonicalTextHash) Write(buf []byte) (int, error) {
return writeCanonical(cth.h, buf, &cth.s)
}
func (cth *canonicalTextHash) Sum(in []byte) []byte {
return cth.h.Sum(in)
}

View File

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

View File

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

View File

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

View File

@ -10,13 +10,7 @@
// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it
// unsuitable for other protocols. RSA should be used in preference in any
// case.
//
// Deprecated: this package was only provided to support ElGamal encryption in
// OpenPGP. The golang.org/x/crypto/openpgp package is now deprecated (see
// https://golang.org/issue/44226), and ElGamal in the OpenPGP ecosystem has
// compatibility and security issues (see https://eprint.iacr.org/2021/923).
// Moreover, this package doesn't protect against side-channel attacks.
package elgamal // import "golang.org/x/crypto/openpgp/elgamal"
package elgamal // import "github.com/ProtonMail/go-crypto/openpgp/elgamal"
import (
"crypto/rand"
@ -77,8 +71,8 @@ func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err
// returns the plaintext of the message. An error can result only if the
// ciphertext is invalid. Users should keep in mind that this is a padding
// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can
// be used to break the cryptosystem. See Chosen Ciphertext Attacks
// Against Protocols Based on the RSA Encryption Standard PKCS #1, Daniel
// be used to break the cryptosystem. See ``Chosen Ciphertext Attacks
// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel
// Bleichenbacher, Advances in Cryptology (Crypto '98),
func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
s := new(big.Int).Exp(c1, priv.X, priv.P)

View File

@ -3,13 +3,7 @@
// license that can be found in the LICENSE file.
// Package errors contains common error types for the OpenPGP packages.
//
// Deprecated: this package is unmaintained except for security fixes. New
// applications should consider a more focused, modern alternative to OpenPGP
// for their specific task. If you are required to interoperate with OpenPGP
// systems and need a maintained package, consider a community fork.
// See https://golang.org/issue/44226.
package errors // import "golang.org/x/crypto/openpgp/errors"
package errors // import "github.com/ProtonMail/go-crypto/openpgp/errors"
import (
"strconv"
@ -47,6 +41,25 @@ 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 {
return "openpgp: signature expired"
}
var ErrSignatureExpired error = signatureExpiredError(0)
type keyExpiredError int
func (ke keyExpiredError) Error() string {
return "openpgp: key expired"
}
var ErrKeyExpired error = keyExpiredError(0)
type keyIncorrectError int
func (ki keyIncorrectError) Error() string {
@ -55,6 +68,14 @@ func (ki keyIncorrectError) Error() string {
var ErrKeyIncorrect error = keyIncorrectError(0)
// KeyInvalidError indicates that the public key parameters are invalid
// as they do not match the private ones
type KeyInvalidError string
func (e KeyInvalidError) Error() string {
return "openpgp: invalid key: " + string(e)
}
type unknownIssuerError int
func (unknownIssuerError) Error() string {
@ -76,3 +97,20 @@ type UnknownPacketTypeError uint8
func (upte UnknownPacketTypeError) Error() string {
return "openpgp: unknown packet type: " + strconv.Itoa(int(upte))
}
// AEADError indicates that there is a problem when initializing or using a
// AEAD instance, configuration struct, nonces or index values.
type AEADError string
func (ae AEADError) Error() string {
return "openpgp: aead error: " + string(ae)
}
// ErrDummyPrivateKey results when operations are attempted on a private key
// that is just a dummy key. See
// https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=fe55ae16ab4e26d8356dc574c9e8bc935e71aef1;hb=23191d7851eae2217ecdac6484349849a24fd94a#l1109
type ErrDummyPrivateKey string
func (dke ErrDummyPrivateKey) Error() string {
return "openpgp: s2k GNU dummy key: " + string(dke)
}

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