mirror of
https://github.com/Mic92/sops-nix.git
synced 2024-12-14 11:57:52 +00:00
Switch the libs to now external ones
This commit is contained in:
parent
6c916c1f57
commit
f636296aff
12 changed files with 22 additions and 474 deletions
|
@ -204,7 +204,7 @@ $ ssh-keygen -t ed25519
|
||||||
|
|
||||||
Converting the public key to the age format works like this:
|
Converting the public key to the age format works like this:
|
||||||
```console
|
```console
|
||||||
$ nix run -f default.nix ssh-pubkey-to-age -c sh -c 'ssh-add -L | ssh-pubkey-to-age'
|
$ nix-shell -p ssh-pubkey-to-age --run "ssh-add -L | ssh-pubkey-to-age"
|
||||||
```
|
```
|
||||||
|
|
||||||
Ssh public key files may also be piped into the `ssh-pubkey-to-age` tool.
|
Ssh public key files may also be piped into the `ssh-pubkey-to-age` tool.
|
||||||
|
@ -212,7 +212,7 @@ Ssh public key files may also be piped into the `ssh-pubkey-to-age` tool.
|
||||||
Finally, you need to convert your private key to the age format:
|
Finally, you need to convert your private key to the age format:
|
||||||
```console
|
```console
|
||||||
$ mkdir -p ~/.config/sops
|
$ mkdir -p ~/.config/sops
|
||||||
$ nix run -f default.nix ssh-privkey-to-age -c ssh-privkey-to-age ~/.ssh/id_ed25519 > ~/.config/sops/keys.txt
|
$ nix-shell -p ssh-privkey-to-age --run "ssh-privkey-to-age ~/.ssh/id_ed25519 > ~/.config/sops/age/keys.txt"
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3a. Get a PGP Public key for your machine
|
### 3a. Get a PGP Public key for your machine
|
||||||
|
@ -252,8 +252,8 @@ If you prefer having a separate GnuPG key, see [Use with GnuPG instead of ssh ke
|
||||||
The `ssh-pubkey-to-age` tool is used to convert any ssh public key to the age format.
|
The `ssh-pubkey-to-age` tool is used to convert any ssh public key to the age format.
|
||||||
This way you can convert any key:
|
This way you can convert any key:
|
||||||
```console
|
```console
|
||||||
$ nix run -f default.nix ssh-pubkey-to-age -c sh -c 'ssh-keyscan my-server.com | ssh-pubkey-to-age'
|
$ nix-shell -p ssh-pubkey-to-age --run 'ssh-keyscan my-server.com | ssh-pubkey-to-age'
|
||||||
$ nix run -f default.nix ssh-pubkey-to-age -c sh -c 'cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-pubkey-to-age'
|
$ nix-shell -p ssh-pubkey-to-age --run 'cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-pubkey-to-age'
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Create a sops file
|
### 4. Create a sops file
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ pkgs ? import <nixpkgs> {} }: let
|
{ pkgs ? import <nixpkgs> {} }: let
|
||||||
vendorSha256 = "sha256:1bizqlj56lka37gbvm37p3yifn7w2z9kfhv486gv40wknzqclq12";
|
vendorSha256 = "sha256:145vmy70mkbciy8mr92nz6w0rwr83884wwwjy4wa587c6wkgs3w2";
|
||||||
|
|
||||||
sops-install-secrets = pkgs.callPackage ./pkgs/sops-install-secrets {
|
sops-install-secrets = pkgs.callPackage ./pkgs/sops-install-secrets {
|
||||||
inherit vendorSha256;
|
inherit vendorSha256;
|
||||||
|
@ -11,8 +11,6 @@ in rec {
|
||||||
Also see https://github.com/Mic92/sops-nix/issues/98
|
Also see https://github.com/Mic92/sops-nix/issues/98
|
||||||
'' pkgs.callPackage ./pkgs/sops-pgp-hook { };
|
'' pkgs.callPackage ./pkgs/sops-pgp-hook { };
|
||||||
sops-import-keys-hook = pkgs.callPackage ./pkgs/sops-import-keys-hook { };
|
sops-import-keys-hook = pkgs.callPackage ./pkgs/sops-import-keys-hook { };
|
||||||
ssh-pubkey-to-age = pkgs.callPackage ./pkgs/ssh-pubkey-to-age { inherit vendorSha256; };
|
|
||||||
ssh-privkey-to-age = pkgs.callPackage ./pkgs/ssh-privkey-to-age { inherit vendorSha256; };
|
|
||||||
inherit sops-install-secrets;
|
inherit sops-install-secrets;
|
||||||
|
|
||||||
# backwards compatibility
|
# backwards compatibility
|
||||||
|
|
6
go.mod
6
go.mod
|
@ -3,12 +3,12 @@ module github.com/Mic92/sops-nix
|
||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
filippo.io/age v1.0.0-rc.3
|
github.com/Mic92/ssh-to-age v0.0.0-20210829164312-1fe15380abe4
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20210707164159-52430bf6b52c
|
github.com/ProtonMail/go-crypto v0.0.0-20210707164159-52430bf6b52c
|
||||||
github.com/mozilla-services/yaml v0.0.0-20191106225358-5c216288813c
|
github.com/mozilla-services/yaml v0.0.0-20191106225358-5c216288813c
|
||||||
go.mozilla.org/sops/v3 v3.7.1
|
go.mozilla.org/sops/v3 v3.7.1
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43
|
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e
|
||||||
)
|
)
|
||||||
|
|
||||||
// see https://github.com/mozilla/sops/pull/925
|
// see https://github.com/mozilla/sops/pull/925
|
||||||
|
|
12
go.sum
12
go.sum
|
@ -9,6 +9,8 @@ filippo.io/age v1.0.0-rc.3 h1:8JjuJ5ffGKDmC4SS0zoyQxZROZX75so768b7AjulKLw=
|
||||||
filippo.io/age v1.0.0-rc.3/go.mod h1:UjINLBMeA60aGZkHCGsmDzKcaXoTTzpvrqQM+Vo3YHU=
|
filippo.io/age v1.0.0-rc.3/go.mod h1:UjINLBMeA60aGZkHCGsmDzKcaXoTTzpvrqQM+Vo3YHU=
|
||||||
filippo.io/edwards25519 v1.0.0-alpha.2/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o=
|
filippo.io/edwards25519 v1.0.0-alpha.2/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o=
|
||||||
filippo.io/edwards25519 v1.0.0-beta.3/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o=
|
filippo.io/edwards25519 v1.0.0-beta.3/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o=
|
||||||
|
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
|
||||||
|
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
|
||||||
github.com/Azure/azure-sdk-for-go v31.2.0+incompatible h1:kZFnTLmdQYNGfakatSivKHUfUnDZhqNdchHD4oIhp5k=
|
github.com/Azure/azure-sdk-for-go v31.2.0+incompatible h1:kZFnTLmdQYNGfakatSivKHUfUnDZhqNdchHD4oIhp5k=
|
||||||
github.com/Azure/azure-sdk-for-go v31.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
github.com/Azure/azure-sdk-for-go v31.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||||
|
@ -41,6 +43,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/Mic92/sops/v3 v3.7.2-0.20210829155005-a7cbb9ffe599 h1:3UXsFmgei0TO2rwvIpW0EQNVJi4SnB3V3GgC/TGndzE=
|
github.com/Mic92/sops/v3 v3.7.2-0.20210829155005-a7cbb9ffe599 h1:3UXsFmgei0TO2rwvIpW0EQNVJi4SnB3V3GgC/TGndzE=
|
||||||
github.com/Mic92/sops/v3 v3.7.2-0.20210829155005-a7cbb9ffe599/go.mod h1:n1KOOXQUp7PbUIYr0yEExC6RWv2hjvQKLNufdWYLNQg=
|
github.com/Mic92/sops/v3 v3.7.2-0.20210829155005-a7cbb9ffe599/go.mod h1:n1KOOXQUp7PbUIYr0yEExC6RWv2hjvQKLNufdWYLNQg=
|
||||||
|
github.com/Mic92/ssh-to-age v0.0.0-20210829164312-1fe15380abe4 h1:PRxM012OHgeUA3yH/FHbyl/q7ep0l1w7t+haJTw6Ozs=
|
||||||
|
github.com/Mic92/ssh-to-age v0.0.0-20210829164312-1fe15380abe4/go.mod h1:Y8QV5VlnhcBamWQHRdVNiqSuip5CDtJdmHxwQvHiXWs=
|
||||||
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
||||||
|
@ -276,8 +280,9 @@ golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPh
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
|
||||||
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
@ -333,8 +338,11 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43 h1:SgQ6LNaYJU0JIuEHv9+s6EbhSCwYeAf5Yvj6lpYlqAE=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/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-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c=
|
||||||
|
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
|
|
@ -1,179 +0,0 @@
|
||||||
// Copyright (c) 2017 Takatoshi Nakagawa
|
|
||||||
// Copyright (c) 2019 Google LLC
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
// Package bech32 is a modified version of the reference implementation of BIP173.
|
|
||||||
package bech32
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
|
|
||||||
|
|
||||||
var generator = []uint32{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3}
|
|
||||||
|
|
||||||
func polymod(values []byte) uint32 {
|
|
||||||
chk := uint32(1)
|
|
||||||
for _, v := range values {
|
|
||||||
top := chk >> 25
|
|
||||||
chk = (chk & 0x1ffffff) << 5
|
|
||||||
chk = chk ^ uint32(v)
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
bit := top >> i & 1
|
|
||||||
if bit == 1 {
|
|
||||||
chk ^= generator[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return chk
|
|
||||||
}
|
|
||||||
|
|
||||||
func hrpExpand(hrp string) []byte {
|
|
||||||
h := []byte(strings.ToLower(hrp))
|
|
||||||
var ret []byte
|
|
||||||
for _, c := range h {
|
|
||||||
ret = append(ret, c>>5)
|
|
||||||
}
|
|
||||||
ret = append(ret, 0)
|
|
||||||
for _, c := range h {
|
|
||||||
ret = append(ret, c&31)
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyChecksum(hrp string, data []byte) bool {
|
|
||||||
return polymod(append(hrpExpand(hrp), data...)) == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func createChecksum(hrp string, data []byte) []byte {
|
|
||||||
values := append(hrpExpand(hrp), data...)
|
|
||||||
values = append(values, []byte{0, 0, 0, 0, 0, 0}...)
|
|
||||||
mod := polymod(values) ^ 1
|
|
||||||
ret := make([]byte, 6)
|
|
||||||
for p := range ret {
|
|
||||||
shift := 5 * (5 - p)
|
|
||||||
ret[p] = byte(mod>>shift) & 31
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertBits(data []byte, frombits, tobits byte, pad bool) ([]byte, error) {
|
|
||||||
var ret []byte
|
|
||||||
acc := uint32(0)
|
|
||||||
bits := byte(0)
|
|
||||||
maxv := byte(1<<tobits - 1)
|
|
||||||
for idx, value := range data {
|
|
||||||
if value>>frombits != 0 {
|
|
||||||
return nil, fmt.Errorf("invalid data range: data[%d]=%d (frombits=%d)", idx, value, frombits)
|
|
||||||
}
|
|
||||||
acc = acc<<frombits | uint32(value)
|
|
||||||
bits += frombits
|
|
||||||
for bits >= tobits {
|
|
||||||
bits -= tobits
|
|
||||||
ret = append(ret, byte(acc>>bits)&maxv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if pad {
|
|
||||||
if bits > 0 {
|
|
||||||
ret = append(ret, byte(acc<<(tobits-bits))&maxv)
|
|
||||||
}
|
|
||||||
} else if bits >= frombits {
|
|
||||||
return nil, fmt.Errorf("illegal zero padding")
|
|
||||||
} else if byte(acc<<(tobits-bits))&maxv != 0 {
|
|
||||||
return nil, fmt.Errorf("non-zero padding")
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode encodes the HRP and a bytes slice to Bech32. If the HRP is uppercase,
|
|
||||||
// the output will be uppercase.
|
|
||||||
func Encode(hrp string, data []byte) (string, error) {
|
|
||||||
values, err := convertBits(data, 8, 5, true)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if len(hrp)+len(values)+7 > 90 {
|
|
||||||
return "", fmt.Errorf("too long: hrp length=%d, data length=%d", len(hrp), len(values))
|
|
||||||
}
|
|
||||||
if len(hrp) < 1 {
|
|
||||||
return "", fmt.Errorf("invalid HRP: %q", hrp)
|
|
||||||
}
|
|
||||||
for p, c := range hrp {
|
|
||||||
if c < 33 || c > 126 {
|
|
||||||
return "", fmt.Errorf("invalid HRP character: hrp[%d]=%d", p, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if strings.ToUpper(hrp) != hrp && strings.ToLower(hrp) != hrp {
|
|
||||||
return "", fmt.Errorf("mixed case HRP: %q", hrp)
|
|
||||||
}
|
|
||||||
lower := strings.ToLower(hrp) == hrp
|
|
||||||
hrp = strings.ToLower(hrp)
|
|
||||||
var ret strings.Builder
|
|
||||||
ret.WriteString(hrp)
|
|
||||||
ret.WriteString("1")
|
|
||||||
for _, p := range values {
|
|
||||||
ret.WriteByte(charset[p])
|
|
||||||
}
|
|
||||||
for _, p := range createChecksum(hrp, values) {
|
|
||||||
ret.WriteByte(charset[p])
|
|
||||||
}
|
|
||||||
if lower {
|
|
||||||
return ret.String(), nil
|
|
||||||
}
|
|
||||||
return strings.ToUpper(ret.String()), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode decodes a Bech32 string. If the string is uppercase, the HRP will be uppercase.
|
|
||||||
func Decode(s string) (hrp string, data []byte, err error) {
|
|
||||||
if len(s) > 90 {
|
|
||||||
return "", nil, fmt.Errorf("too long: len=%d", len(s))
|
|
||||||
}
|
|
||||||
if strings.ToLower(s) != s && strings.ToUpper(s) != s {
|
|
||||||
return "", nil, fmt.Errorf("mixed case")
|
|
||||||
}
|
|
||||||
pos := strings.LastIndex(s, "1")
|
|
||||||
if pos < 1 || pos+7 > len(s) {
|
|
||||||
return "", nil, fmt.Errorf("separator '1' at invalid position: pos=%d, len=%d", pos, len(s))
|
|
||||||
}
|
|
||||||
hrp = s[:pos]
|
|
||||||
for p, c := range hrp {
|
|
||||||
if c < 33 || c > 126 {
|
|
||||||
return "", nil, fmt.Errorf("invalid character human-readable part: s[%d]=%d", p, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s = strings.ToLower(s)
|
|
||||||
for p, c := range s[pos+1:] {
|
|
||||||
d := strings.IndexRune(charset, c)
|
|
||||||
if d == -1 {
|
|
||||||
return "", nil, fmt.Errorf("invalid character data part: s[%d]=%v", p, c)
|
|
||||||
}
|
|
||||||
data = append(data, byte(d))
|
|
||||||
}
|
|
||||||
if !verifyChecksum(hrp, data) {
|
|
||||||
return "", nil, fmt.Errorf("invalid checksum")
|
|
||||||
}
|
|
||||||
data, err = convertBits(data[:len(data)-6], 5, 8, false)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
return hrp, data, nil
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
// Copyright (c) 2013-2017 The btcsuite developers
|
|
||||||
// Copyright (c) 2016-2017 The Lightning Network Developers
|
|
||||||
// Copyright (c) 2019 Google LLC
|
|
||||||
//
|
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
|
||||||
// copyright notice and this permission notice appear in all copies.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
package bech32_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"filippo.io/age/internal/bech32"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBech32(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
str string
|
|
||||||
valid bool
|
|
||||||
}{
|
|
||||||
{"A12UEL5L", true},
|
|
||||||
{"a12uel5l", true},
|
|
||||||
{"an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs", true},
|
|
||||||
{"abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", true},
|
|
||||||
{"11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j", true},
|
|
||||||
{"split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", true},
|
|
||||||
|
|
||||||
// invalid checksum
|
|
||||||
{"split1checkupstagehandshakeupstreamerranterredcaperred2y9e2w", false},
|
|
||||||
// invalid character (space) in hrp
|
|
||||||
{"s lit1checkupstagehandshakeupstreamerranterredcaperredp8hs2p", false},
|
|
||||||
{"split1cheo2y9e2w", false}, // invalid character (o) in data part
|
|
||||||
{"split1a2y9w", false}, // too short data part
|
|
||||||
{"1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", false}, // empty hrp
|
|
||||||
// invalid character (DEL) in hrp
|
|
||||||
{"spl" + string(rune(127)) + "t1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", false},
|
|
||||||
// too long
|
|
||||||
{"11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqsqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j", false},
|
|
||||||
|
|
||||||
// BIP 173 invalid vectors.
|
|
||||||
{"an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx", false},
|
|
||||||
{"pzry9x0s0muk", false},
|
|
||||||
{"1pzry9x0s0muk", false},
|
|
||||||
{"x1b4n0q5v", false},
|
|
||||||
{"li1dgmt3", false},
|
|
||||||
{"de1lg7wt\xff", false},
|
|
||||||
{"A1G7SGD8", false},
|
|
||||||
{"10a06t8", false},
|
|
||||||
{"1qzzfhee", false},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
str := test.str
|
|
||||||
hrp, decoded, err := bech32.Decode(str)
|
|
||||||
if !test.valid {
|
|
||||||
// Invalid string decoding should result in error.
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("expected decoding to fail for invalid string %v", test.str)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Valid string decoding should result in no error.
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("expected string to be valid bech32: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that it encodes to the same string.
|
|
||||||
encoded, err := bech32.Encode(hrp, decoded)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("encoding failed: %v", err)
|
|
||||||
}
|
|
||||||
if encoded != str {
|
|
||||||
t.Errorf("expected data to encode to %v, but got %v", str, encoded)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flip a bit in the string an make sure it is caught.
|
|
||||||
pos := strings.LastIndexAny(str, "1")
|
|
||||||
flipped := str[:pos+1] + string((str[pos+1] ^ 1)) + str[pos+2:]
|
|
||||||
if _, _, err = bech32.Decode(flipped); err == nil {
|
|
||||||
t.Error("expected decoding to fail")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
package agessh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/ed25519"
|
|
||||||
"crypto/sha512"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/Mic92/sops-nix/pkgs/bech32"
|
|
||||||
"golang.org/x/crypto/curve25519"
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ed25519PrivateKeyToCurve25519(pk ed25519.PrivateKey) ([]byte, error) {
|
|
||||||
h := sha512.New()
|
|
||||||
_, err := h.Write(pk.Seed())
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, err
|
|
||||||
}
|
|
||||||
out := h.Sum(nil)
|
|
||||||
return out[:curve25519.ScalarSize], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func SSHPrivateKeyToBech32(sshPrivateKey []byte) (string, error) {
|
|
||||||
privateKey, err := ssh.ParseRawPrivateKey(sshPrivateKey)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
ed25519Key, ok := privateKey.(*ed25519.PrivateKey)
|
|
||||||
if !ok {
|
|
||||||
return "", fmt.Errorf("Only ED25519 keys are supported, got: %s", reflect.TypeOf(privateKey))
|
|
||||||
}
|
|
||||||
bytes, err := ed25519PrivateKeyToCurve25519(*ed25519Key)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
s, err := bech32.Encode("AGE-SECRET-KEY-", bytes)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return strings.ToUpper(s), nil
|
|
||||||
}
|
|
|
@ -17,8 +17,8 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Mic92/sops-nix/pkgs/sops-install-secrets/agessh"
|
|
||||||
"github.com/Mic92/sops-nix/pkgs/sops-install-secrets/sshkeys"
|
"github.com/Mic92/sops-nix/pkgs/sops-install-secrets/sshkeys"
|
||||||
|
agessh "github.com/Mic92/ssh-to-age"
|
||||||
|
|
||||||
"github.com/mozilla-services/yaml"
|
"github.com/mozilla-services/yaml"
|
||||||
"go.mozilla.org/sops/v3/decrypt"
|
"go.mozilla.org/sops/v3/decrypt"
|
||||||
|
@ -533,13 +533,13 @@ func importAgeSSHKeys(keyPaths []string, ageFilePath string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Cannot read ssh key '%s': %w", p, err)
|
return fmt.Errorf("Cannot read ssh key '%s': %w", p, err)
|
||||||
}
|
}
|
||||||
// Convert the key to bech32
|
// Convert the key to age
|
||||||
bech32, err := agessh.SSHPrivateKeyToBech32(sshKey)
|
bech32, err := agessh.SSHPrivateKeyToAge(sshKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Cannot convert ssh key '%s': %w", p, err)
|
return fmt.Errorf("Cannot convert ssh key '%s': %w", p, err)
|
||||||
}
|
}
|
||||||
// Append it to the file
|
// Append it to the file
|
||||||
_, err = ageFile.WriteString(bech32 + "\n")
|
_, err = ageFile.WriteString(*bech32 + "\n")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Cannot write key to age file: %w", err)
|
return fmt.Errorf("Cannot write key to age file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
{ stdenv, lib, buildGoModule, path, pkgs, vendorSha256, go }:
|
|
||||||
buildGoModule {
|
|
||||||
pname = "ssh-privkey-to-age";
|
|
||||||
version = "0.0.1";
|
|
||||||
|
|
||||||
src = ../..;
|
|
||||||
|
|
||||||
subPackages = [ "pkgs/ssh-privkey-to-age" ];
|
|
||||||
|
|
||||||
inherit vendorSha256;
|
|
||||||
|
|
||||||
meta = with lib; {
|
|
||||||
description = "Converter that converts SSH private keys into age keys";
|
|
||||||
homepage = "https://github.com/Mic92/sops-nix";
|
|
||||||
license = licenses.mit;
|
|
||||||
maintainers = with maintainers; [ mic92 ];
|
|
||||||
platforms = platforms.linux;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/Mic92/sops-nix/pkgs/sops-install-secrets/agessh"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if len(os.Args) != 2 {
|
|
||||||
println("Usage: " + os.Args[0] + " [path to ssh private key]")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
sshKey, err := ioutil.ReadFile(os.Args[1])
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("Cannot read ssh key '%s': %w", os.Args[1], err))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the key to bech32
|
|
||||||
bech32, err := agessh.SSHPrivateKeyToBech32(sshKey)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("Cannot convert ssh key '%s': %w", os.Args[1], err))
|
|
||||||
}
|
|
||||||
fmt.Println(bech32)
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
{ stdenv, lib, buildGoModule, path, pkgs, vendorSha256, go }:
|
|
||||||
buildGoModule {
|
|
||||||
pname = "ssh-pubkey-to-age";
|
|
||||||
version = "0.0.1";
|
|
||||||
|
|
||||||
src = ../..;
|
|
||||||
|
|
||||||
subPackages = [ "pkgs/ssh-pubkey-to-age" ];
|
|
||||||
|
|
||||||
inherit vendorSha256;
|
|
||||||
|
|
||||||
meta = with lib; {
|
|
||||||
description = "Converter that converts SSH public keys into age keys";
|
|
||||||
homepage = "https://github.com/Mic92/sops-nix";
|
|
||||||
license = licenses.mit;
|
|
||||||
maintainers = with maintainers; [ mic92 ];
|
|
||||||
platforms = platforms.linux;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"crypto/ed25519"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"filippo.io/edwards25519"
|
|
||||||
"github.com/Mic92/sops-nix/pkgs/bech32"
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ed25519PublicKeyToCurve25519(pk ed25519.PublicKey) ([]byte, error) {
|
|
||||||
// See https://blog.filippo.io/using-ed25519-keys-for-encryption and
|
|
||||||
// https://pkg.go.dev/filippo.io/edwards25519#Point.BytesMontgomery.
|
|
||||||
p, err := new(edwards25519.Point).SetBytes(pk)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return p.BytesMontgomery(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if len(os.Args) != 1 {
|
|
||||||
println("Usage: " + os.Args[0])
|
|
||||||
println("Pipe a SSH public key or the output of ssh-keyscan into it")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
|
||||||
for scanner.Scan() {
|
|
||||||
text := scanner.Text() + "\n"
|
|
||||||
var err error
|
|
||||||
var pk ssh.PublicKey
|
|
||||||
if strings.HasPrefix(text, "ssh-") {
|
|
||||||
pk, _, _, _, err = ssh.ParseAuthorizedKey([]byte(text))
|
|
||||||
} else {
|
|
||||||
_, _, pk, _, _, err = ssh.ParseKnownHosts([]byte(text))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
// We only care about ed25519
|
|
||||||
if pk.Type() != ssh.KeyAlgoED25519 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Get the bytes
|
|
||||||
cpk, ok := pk.(ssh.CryptoPublicKey)
|
|
||||||
if !ok {
|
|
||||||
panic(errors.New("pk does not implement ssh.CryptoPublicKey"))
|
|
||||||
}
|
|
||||||
epk, ok := cpk.CryptoPublicKey().(ed25519.PublicKey)
|
|
||||||
if !ok {
|
|
||||||
panic(errors.New("unexpected public key type"))
|
|
||||||
}
|
|
||||||
// Convert the key to curve ed25519
|
|
||||||
mpk, err := ed25519PublicKeyToCurve25519(epk)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("invalid Ed25519 public key: %v", err))
|
|
||||||
}
|
|
||||||
// Encode the key
|
|
||||||
s, err := bech32.Encode("age", mpk)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fmt.Println(s)
|
|
||||||
}
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue