Compare commits
15 commits
Author | SHA1 | Date | |
---|---|---|---|
aa96303d43 | |||
8d3686eb14 | |||
6b2e5526b2 | |||
d128cfa7ce | |||
3f6b9cd2af | |||
6a16789886 | |||
1823aaa5e0 | |||
810aa02bdd | |||
|
1786734c0a | ||
|
d47a4596ef | ||
|
fc94d7cd7d | ||
|
2e6d92c753 | ||
|
5c6152b4ed | ||
|
e3053142f5 | ||
|
d49f732c71 |
23 changed files with 742 additions and 598 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -31,4 +31,4 @@ sigtool
|
||||||
*.pub
|
*.pub
|
||||||
*.key
|
*.key
|
||||||
*.sig
|
*.sig
|
||||||
|
releases/*
|
||||||
|
|
2
.mise.toml
Normal file
2
.mise.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[tools]
|
||||||
|
golang = "1.24"
|
|
@ -40,7 +40,7 @@ You need two things:
|
||||||
|
|
||||||
Next, build sigtool:
|
Next, build sigtool:
|
||||||
|
|
||||||
git clone https://github.com/opencoff/sigtool
|
git clone https://git.rgst.io/homelab/sigtool/v3
|
||||||
cd sigtool
|
cd sigtool
|
||||||
make
|
make
|
||||||
|
|
||||||
|
@ -101,6 +101,10 @@ e.g., to verify the signature of *archive.tar.gz* against
|
||||||
sigtool verify /tmp/testkey.pub archive.sig archive.tar.gz
|
sigtool verify /tmp/testkey.pub archive.sig archive.tar.gz
|
||||||
|
|
||||||
|
|
||||||
|
You can also pass a public key as a string (instead of a file):
|
||||||
|
|
||||||
|
sigtool verify iF84Dymq/bAEnUMK6DRIHWAQDRD8FwDDDfsgFfzdjWM= archive.sig archive.tar.gz
|
||||||
|
|
||||||
Note that signing and verifying can also work with OpenSSH ed25519
|
Note that signing and verifying can also work with OpenSSH ed25519
|
||||||
keys.
|
keys.
|
||||||
|
|
||||||
|
|
102
build
102
build
|
@ -13,12 +13,13 @@
|
||||||
#
|
#
|
||||||
# License: GPLv2
|
# License: GPLv2
|
||||||
#
|
#
|
||||||
Progs=".:sigtool"
|
Progs="src:sigtool"
|
||||||
|
|
||||||
# Relative path to protobuf sources
|
# Relative path to protobuf sources
|
||||||
# e.g. src/foo/a.proto
|
# e.g. src/foo/a.proto
|
||||||
Protobufs="internal/pb/hdr.proto"
|
Protobufs="internal/pb/hdr.proto"
|
||||||
|
|
||||||
|
#set -x
|
||||||
|
|
||||||
# -- DO NOT CHANGE ANYTHING AFTER THIS --
|
# -- DO NOT CHANGE ANYTHING AFTER THIS --
|
||||||
|
|
||||||
|
@ -28,8 +29,10 @@ PWD=`pwd`
|
||||||
Static=0
|
Static=0
|
||||||
Dryrun=0
|
Dryrun=0
|
||||||
Prodver=""
|
Prodver=""
|
||||||
|
Repover=""
|
||||||
Verbose=0
|
Verbose=0
|
||||||
Go=`which go`
|
Go=`which go`
|
||||||
|
Bindir=$PWD/bin
|
||||||
|
|
||||||
die() {
|
die() {
|
||||||
echo "$Z: $@" 1>&2
|
echo "$Z: $@" 1>&2
|
||||||
|
@ -47,18 +50,56 @@ case $BASH_VERSION in
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
getvcs_version() {
|
||||||
|
local rev=
|
||||||
|
local prodv=
|
||||||
|
local git=`which git`
|
||||||
|
local hg=`which hg`
|
||||||
|
|
||||||
|
if [ -n "$git" ]; then
|
||||||
|
local xrev=$(git describe --always --dirty --long --abbrev=12) || exit 1
|
||||||
|
rev="git:$xrev"
|
||||||
|
prodv=$(git tag --list | sort -V | tail -1)
|
||||||
|
elif [ -n "$hg" ]; then
|
||||||
|
local xrev=$(hg id --id) || exit 1
|
||||||
|
local brev=${xrev%+}
|
||||||
|
if [ "$brev" != "$xrev" ]; then
|
||||||
|
rev="hg:${brev}-dirty"
|
||||||
|
else
|
||||||
|
rev="hg:${brev}"
|
||||||
|
fi
|
||||||
|
prodv=$(hg log -r "branch(stable) and tag()" -T "{tags}\n" | sort -V | tail -1)
|
||||||
|
else
|
||||||
|
warn "no git or hg found; can't get VCS info"
|
||||||
|
rev="UNKNOWN-VER"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -n "$Prodver" ] && prodv=$Prodver
|
||||||
|
|
||||||
|
echo "$rev $prodv"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
read -r Repover Prodver <<< $(getvcs_version)
|
||||||
|
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
|
declare -a progv=($Progs)
|
||||||
|
declare n=${#progv[@]}
|
||||||
|
declare pstr=
|
||||||
|
|
||||||
|
for ((i=0; i < n; i++)); do
|
||||||
|
local ent=${progv[$i]}
|
||||||
|
local dir=${ent%%:*}
|
||||||
|
local tool=${ent##*:}
|
||||||
|
pstr=$(printf "$pstr\n\t%s $Prodver $Repover (from ./%s)" $tool $dir)
|
||||||
|
done
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
$0 - A Go production build tool that adds git-repository information,
|
$0 - A Go production build tool that adds git-repository information,
|
||||||
product version, build-timestamp etc. It supports cross-compilation,
|
product version, build-timestamp etc. It supports cross-compilation,
|
||||||
static linking and generating protobuf output.
|
static linking and generating protobuf output.
|
||||||
|
|
||||||
If needed, it uses the gogo-slick protobuf compiler [github.com/gogo/protobuf].
|
|
||||||
|
|
||||||
Build output is in bin/\$OS-\$CPU for a given OS, CPU combination.
|
Build output is in bin/\$OS-\$CPU for a given OS, CPU combination.
|
||||||
|
|
||||||
Usage: $0
|
Usage: $0
|
||||||
|
@ -67,13 +108,14 @@ Usage: $0
|
||||||
Where OS-ARCH denotes one of the valid OS, ARCH combinations supported by 'go'.
|
Where OS-ARCH denotes one of the valid OS, ARCH combinations supported by 'go'.
|
||||||
And, PROGS is one or more go programs.
|
And, PROGS is one or more go programs.
|
||||||
|
|
||||||
With no arguments, $0 builds: $Progs (source in ./src/)
|
With no arguments, $0 builds: $pstr
|
||||||
|
|
||||||
The repository's latest tag is used as the default version of the software being
|
The repository's latest tag is used as the default version of the software being
|
||||||
built.
|
built. The current repository version is $Repover.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-h, --help Show this help message and quit
|
-h, --help Show this help message and quit
|
||||||
|
-b D, --bindir=D Put the binaries in the directory 'D' [$Bindir]
|
||||||
-s, --static Build a statically linked binary [False]
|
-s, --static Build a statically linked binary [False]
|
||||||
-V N, --version=N Use 'N' as the product version string [$Prodver]
|
-V N, --version=N Use 'N' as the product version string [$Prodver]
|
||||||
-a X, --arch=X Cross compile for OS-CPU 'X' [$hostos-$hostcpu]
|
-a X, --arch=X Cross compile for OS-CPU 'X' [$hostos-$hostcpu]
|
||||||
|
@ -156,6 +198,14 @@ do
|
||||||
ac_prev=Arch
|
ac_prev=Arch
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
-b|--bindir)
|
||||||
|
ac_prev=Bindir
|
||||||
|
;;
|
||||||
|
|
||||||
|
--bindir=*)
|
||||||
|
Bindir=$ac_optarg
|
||||||
|
;;
|
||||||
|
|
||||||
--version=*)
|
--version=*)
|
||||||
Prodver=$ac_optarg
|
Prodver=$ac_optarg
|
||||||
;;
|
;;
|
||||||
|
@ -280,6 +330,7 @@ buildproto() {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# the rest has to execute in the context of main shell (not funcs)
|
# the rest has to execute in the context of main shell (not funcs)
|
||||||
|
|
||||||
hostos=$($Go env GOHOSTOS) || exit 1
|
hostos=$($Go env GOHOSTOS) || exit 1
|
||||||
|
@ -336,36 +387,13 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# This is where build outputs go
|
# This is where build outputs go
|
||||||
Bindir=$PWD/bin/$cross
|
Outdir=$Bindir/$cross
|
||||||
Hostbindir=$PWD/bin/$hostos-$hostcpu
|
Hostbindir=$Bindir/$hostos-$hostcpu
|
||||||
export PATH=$Hostbindir:$PATH
|
export PATH=$Hostbindir:$PATH
|
||||||
|
|
||||||
[ -d $Bindir ] || mkdir -p $Bindir
|
[ -d $Outdir ] || mkdir -p $Outdir
|
||||||
[ -d $Hostbindir ] || mkdir -p $Hostbindir
|
[ -d $Hostbindir ] || mkdir -p $Hostbindir
|
||||||
|
|
||||||
# Get git/hg version info for the build
|
|
||||||
if [ -d "./.hg" ]; then
|
|
||||||
xrev=$(hg id --id) || exit 1
|
|
||||||
brev=${xrev%+}
|
|
||||||
if [ "$brev" != "$xrev" ]; then
|
|
||||||
rev="hg:${brev}-dirty"
|
|
||||||
else
|
|
||||||
rev="hg:${brev}"
|
|
||||||
fi
|
|
||||||
if [ -z "$Prodver" ]; then
|
|
||||||
Prodver=$(hg log -r "branch(stable) and tag()" -T "{tags}\n" | tail -1)
|
|
||||||
fi
|
|
||||||
elif [ -d "./.git" ]; then
|
|
||||||
xrev=$(git describe --always --dirty --long --abbrev=12) || exit 1
|
|
||||||
rev="git:$xrev"
|
|
||||||
if [ -z "$Prodver" ]; then
|
|
||||||
Prodver=$(git tag --list | tail -1)
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
rev="UNKNOWN-VER"
|
|
||||||
echo "$0: Can't find version info" 1>&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
# Do Protobufs if needed
|
# Do Protobufs if needed
|
||||||
if [ -n "$Protobufs" ]; then
|
if [ -n "$Protobufs" ]; then
|
||||||
|
@ -374,10 +402,10 @@ if [ -n "$Protobufs" ]; then
|
||||||
set -e
|
set -e
|
||||||
fi
|
fi
|
||||||
|
|
||||||
repover="main.RepoVersion=$rev"
|
# Get git/hg version info for the build
|
||||||
|
repover="main.RepoVersion=$Repover"
|
||||||
prodver="main.ProductVersion=$Prodver"
|
prodver="main.ProductVersion=$Prodver"
|
||||||
date="main.Buildtime=`date -u '+%Y-%m-%dT%H:%M.%SZ'`"
|
ldflags="-ldflags \"-X $repover -X $prodver $ldflags -buildid=\""
|
||||||
ldflags="-ldflags \"-X $repover -X $prodver -X $date $ldflags\""
|
|
||||||
vflag=""
|
vflag=""
|
||||||
|
|
||||||
[ $Verbose -gt 0 ] && vflag="-v"
|
[ $Verbose -gt 0 ] && vflag="-v"
|
||||||
|
@ -406,7 +434,9 @@ case $Tool in
|
||||||
all="$@"
|
all="$@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Building $Prodver ($rev), $cross $msg .."
|
[ -z "$all" ] && die "No programs specified. Try '$Z --help'"
|
||||||
|
|
||||||
|
echo "Building $Prodver ($Repover), $cross $msg .."
|
||||||
|
|
||||||
for p in $all; do
|
for p in $all; do
|
||||||
if echo $p | grep -q ':' ; then
|
if echo $p | grep -q ':' ; then
|
||||||
|
@ -424,7 +454,7 @@ case $Tool in
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo " $dir: $out .. "
|
echo " $dir: $out .. "
|
||||||
$e eval $Go build $vflag -o $Bindir/$out $isuffix "$ldflags" ./$dir || exit 1
|
$e eval $Go build $vflag -trimpath -o $Outdir/$out $isuffix "$ldflags" ./$dir || exit 1
|
||||||
done
|
done
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
25
go.mod
25
go.mod
|
@ -1,20 +1,25 @@
|
||||||
module github.com/opencoff/sigtool
|
module git.rgst.io/homelab/sigtool/v3
|
||||||
|
|
||||||
go 1.21.1
|
go 1.24.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a
|
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a
|
||||||
github.com/opencoff/go-mmap v0.1.1
|
github.com/opencoff/go-fio v0.5.14
|
||||||
github.com/opencoff/go-utils v0.9.0
|
github.com/opencoff/go-mmap v0.1.5
|
||||||
github.com/opencoff/pflag v1.0.6-sh1
|
github.com/opencoff/go-utils v1.0.2
|
||||||
golang.org/x/crypto v0.17.0
|
github.com/opencoff/pflag v1.0.7
|
||||||
google.golang.org/protobuf v1.32.0
|
github.com/planetscale/vtprotobuf v0.6.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
golang.org/x/crypto v0.36.0
|
||||||
|
google.golang.org/protobuf v1.36.5
|
||||||
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
golang.org/x/sys v0.16.0 // indirect
|
github.com/pkg/xattr v0.4.10 // indirect
|
||||||
golang.org/x/term v0.15.0 // indirect
|
github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
|
||||||
|
golang.org/x/sys v0.31.0 // indirect
|
||||||
|
golang.org/x/term v0.30.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
//replace github.com/opencoff/go-mmap => ../go-mmap
|
//replace github.com/opencoff/go-mmap => ../go-mmap
|
||||||
|
//replace github.com/opencoff/go-utils => ../go-utils
|
||||||
|
|
47
go.sum
47
go.sum
|
@ -2,23 +2,38 @@ github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a h1:saTgr5tMLFn
|
||||||
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a/go.mod h1:Bw9BbhOJVNR+t0jCqx2GC6zv0TGBsShs56Y3gfSCvl0=
|
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a/go.mod h1:Bw9BbhOJVNR+t0jCqx2GC6zv0TGBsShs56Y3gfSCvl0=
|
||||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/opencoff/go-mmap v0.1.1 h1:Z1B8CECT+5Tf6tcqWgf2BR0ufFnQeziNlcI8CzCt4o0=
|
github.com/opencoff/go-fio v0.5.14 h1:PGi4XLLO4RSuc3m5exY0G2vweov6w3UThhScehBfM8c=
|
||||||
github.com/opencoff/go-mmap v0.1.1/go.mod h1:+UjRnKQ3l5dLqSNAczz7zKI8LJ7mBhJhaSqU4S91tFs=
|
github.com/opencoff/go-fio v0.5.14/go.mod h1:hoSySYpavRnfQUsxzUgadk31kYiNQhMDvA2MObsXKf8=
|
||||||
github.com/opencoff/go-utils v0.9.0 h1:qJcRsjLHADmej3/BkH6cLX3pxapLwHf9uSN0E7vvZf4=
|
github.com/opencoff/go-mmap v0.1.5 h1:RKPtevC4mOW5bi9skBPPo4nFTIH4lVWAL20Tff+FjLg=
|
||||||
github.com/opencoff/go-utils v0.9.0/go.mod h1:IHjYSeM+bOKhCD2rBEba4/0C7Apko+KZKKyFgDF43Sc=
|
github.com/opencoff/go-mmap v0.1.5/go.mod h1:y/6Jk/tDUc00k3oSQpiJX++20Nw7xFSlc5kLkhGnRXw=
|
||||||
github.com/opencoff/pflag v1.0.6-sh1 h1:6RO8GgnpH928yu6earGDD01FnFT//bDJ1hCovcVVqY4=
|
github.com/opencoff/go-utils v1.0.2 h1:BANRL8ZxgHpuo8gQBAzT3M9Im3aNFhaWW28jhc86LNs=
|
||||||
github.com/opencoff/pflag v1.0.6-sh1/go.mod h1:2bXtpAD/5h/2LarkbsRwiUxqnvB1nZBzn9Xjad1P41A=
|
github.com/opencoff/go-utils v1.0.2/go.mod h1:eZkEVQVzNfuE8uGepyhscMsqcXq7liGbBHYYwgYaoy8=
|
||||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
github.com/opencoff/pflag v1.0.7 h1:o5cQIuX75bDcdJ6AXl68gzpA72a3CJ2MPStaMnEuwi4=
|
||||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
github.com/opencoff/pflag v1.0.7/go.mod h1:2bXtpAD/5h/2LarkbsRwiUxqnvB1nZBzn9Xjad1P41A=
|
||||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
github.com/pkg/xattr v0.4.10 h1:Qe0mtiNFHQZ296vRgUjRCoPHPqH7VdTOrZx3g0T+pGA=
|
||||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
github.com/pkg/xattr v0.4.10/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU=
|
||||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
github.com/planetscale/vtprotobuf v0.6.0 h1:nBeETjudeJ5ZgBHUz1fVHvbqUKnYOXNhsIEabROxmNA=
|
||||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
github.com/planetscale/vtprotobuf v0.6.0/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
|
||||||
|
github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg=
|
||||||
|
github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||||
|
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
||||||
|
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||||
|
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||||
|
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||||
|
golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
|
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
||||||
|
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
||||||
|
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
||||||
|
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.28.1
|
// protoc-gen-go v1.32.0
|
||||||
// protoc v3.21.12
|
// protoc v3.21.12
|
||||||
// source: internal/pb/hdr.proto
|
// source: internal/pb/hdr.proto
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
// Code generated by protoc-gen-go-vtproto. DO NOT EDIT.
|
// Code generated by protoc-gen-go-vtproto. DO NOT EDIT.
|
||||||
// protoc-gen-go-vtproto version: v0.5.0
|
// protoc-gen-go-vtproto version: v0.6.0
|
||||||
// source: internal/pb/hdr.proto
|
// source: internal/pb/hdr.proto
|
||||||
|
|
||||||
package pb
|
package pb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
fmt "fmt"
|
fmt "fmt"
|
||||||
|
protohelpers "github.com/planetscale/vtprotobuf/protohelpers"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
io "io"
|
io "io"
|
||||||
bits "math/bits"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -55,7 +55,7 @@ func (m *Header) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
i -= size
|
i -= size
|
||||||
i = encodeVarint(dAtA, i, uint64(size))
|
i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0x2a
|
dAtA[i] = 0x2a
|
||||||
}
|
}
|
||||||
|
@ -63,26 +63,26 @@ func (m *Header) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||||
if len(m.Sender) > 0 {
|
if len(m.Sender) > 0 {
|
||||||
i -= len(m.Sender)
|
i -= len(m.Sender)
|
||||||
copy(dAtA[i:], m.Sender)
|
copy(dAtA[i:], m.Sender)
|
||||||
i = encodeVarint(dAtA, i, uint64(len(m.Sender)))
|
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Sender)))
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0x22
|
dAtA[i] = 0x22
|
||||||
}
|
}
|
||||||
if len(m.Pk) > 0 {
|
if len(m.Pk) > 0 {
|
||||||
i -= len(m.Pk)
|
i -= len(m.Pk)
|
||||||
copy(dAtA[i:], m.Pk)
|
copy(dAtA[i:], m.Pk)
|
||||||
i = encodeVarint(dAtA, i, uint64(len(m.Pk)))
|
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Pk)))
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0x1a
|
dAtA[i] = 0x1a
|
||||||
}
|
}
|
||||||
if len(m.Salt) > 0 {
|
if len(m.Salt) > 0 {
|
||||||
i -= len(m.Salt)
|
i -= len(m.Salt)
|
||||||
copy(dAtA[i:], m.Salt)
|
copy(dAtA[i:], m.Salt)
|
||||||
i = encodeVarint(dAtA, i, uint64(len(m.Salt)))
|
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Salt)))
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0x12
|
dAtA[i] = 0x12
|
||||||
}
|
}
|
||||||
if m.ChunkSize != 0 {
|
if m.ChunkSize != 0 {
|
||||||
i = encodeVarint(dAtA, i, uint64(m.ChunkSize))
|
i = protohelpers.EncodeVarint(dAtA, i, uint64(m.ChunkSize))
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0x8
|
dAtA[i] = 0x8
|
||||||
}
|
}
|
||||||
|
@ -122,31 +122,20 @@ func (m *WrappedKey) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||||
if len(m.Nonce) > 0 {
|
if len(m.Nonce) > 0 {
|
||||||
i -= len(m.Nonce)
|
i -= len(m.Nonce)
|
||||||
copy(dAtA[i:], m.Nonce)
|
copy(dAtA[i:], m.Nonce)
|
||||||
i = encodeVarint(dAtA, i, uint64(len(m.Nonce)))
|
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Nonce)))
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0x12
|
dAtA[i] = 0x12
|
||||||
}
|
}
|
||||||
if len(m.DKey) > 0 {
|
if len(m.DKey) > 0 {
|
||||||
i -= len(m.DKey)
|
i -= len(m.DKey)
|
||||||
copy(dAtA[i:], m.DKey)
|
copy(dAtA[i:], m.DKey)
|
||||||
i = encodeVarint(dAtA, i, uint64(len(m.DKey)))
|
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.DKey)))
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0xa
|
dAtA[i] = 0xa
|
||||||
}
|
}
|
||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeVarint(dAtA []byte, offset int, v uint64) int {
|
|
||||||
offset -= sov(v)
|
|
||||||
base := offset
|
|
||||||
for v >= 1<<7 {
|
|
||||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
|
||||||
v >>= 7
|
|
||||||
offset++
|
|
||||||
}
|
|
||||||
dAtA[offset] = uint8(v)
|
|
||||||
return base
|
|
||||||
}
|
|
||||||
func (m *Header) SizeVT() (n int) {
|
func (m *Header) SizeVT() (n int) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return 0
|
return 0
|
||||||
|
@ -154,24 +143,24 @@ func (m *Header) SizeVT() (n int) {
|
||||||
var l int
|
var l int
|
||||||
_ = l
|
_ = l
|
||||||
if m.ChunkSize != 0 {
|
if m.ChunkSize != 0 {
|
||||||
n += 1 + sov(uint64(m.ChunkSize))
|
n += 1 + protohelpers.SizeOfVarint(uint64(m.ChunkSize))
|
||||||
}
|
}
|
||||||
l = len(m.Salt)
|
l = len(m.Salt)
|
||||||
if l > 0 {
|
if l > 0 {
|
||||||
n += 1 + l + sov(uint64(l))
|
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||||
}
|
}
|
||||||
l = len(m.Pk)
|
l = len(m.Pk)
|
||||||
if l > 0 {
|
if l > 0 {
|
||||||
n += 1 + l + sov(uint64(l))
|
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||||
}
|
}
|
||||||
l = len(m.Sender)
|
l = len(m.Sender)
|
||||||
if l > 0 {
|
if l > 0 {
|
||||||
n += 1 + l + sov(uint64(l))
|
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||||
}
|
}
|
||||||
if len(m.Keys) > 0 {
|
if len(m.Keys) > 0 {
|
||||||
for _, e := range m.Keys {
|
for _, e := range m.Keys {
|
||||||
l = e.SizeVT()
|
l = e.SizeVT()
|
||||||
n += 1 + l + sov(uint64(l))
|
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
n += len(m.unknownFields)
|
n += len(m.unknownFields)
|
||||||
|
@ -186,22 +175,16 @@ func (m *WrappedKey) SizeVT() (n int) {
|
||||||
_ = l
|
_ = l
|
||||||
l = len(m.DKey)
|
l = len(m.DKey)
|
||||||
if l > 0 {
|
if l > 0 {
|
||||||
n += 1 + l + sov(uint64(l))
|
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||||
}
|
}
|
||||||
l = len(m.Nonce)
|
l = len(m.Nonce)
|
||||||
if l > 0 {
|
if l > 0 {
|
||||||
n += 1 + l + sov(uint64(l))
|
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||||
}
|
}
|
||||||
n += len(m.unknownFields)
|
n += len(m.unknownFields)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func sov(x uint64) (n int) {
|
|
||||||
return (bits.Len64(x|1) + 6) / 7
|
|
||||||
}
|
|
||||||
func soz(x uint64) (n int) {
|
|
||||||
return sov(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
|
||||||
}
|
|
||||||
func (m *Header) UnmarshalVT(dAtA []byte) error {
|
func (m *Header) UnmarshalVT(dAtA []byte) error {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
iNdEx := 0
|
||||||
|
@ -210,7 +193,7 @@ func (m *Header) UnmarshalVT(dAtA []byte) error {
|
||||||
var wire uint64
|
var wire uint64
|
||||||
for shift := uint(0); ; shift += 7 {
|
for shift := uint(0); ; shift += 7 {
|
||||||
if shift >= 64 {
|
if shift >= 64 {
|
||||||
return ErrIntOverflow
|
return protohelpers.ErrIntOverflow
|
||||||
}
|
}
|
||||||
if iNdEx >= l {
|
if iNdEx >= l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -238,7 +221,7 @@ func (m *Header) UnmarshalVT(dAtA []byte) error {
|
||||||
m.ChunkSize = 0
|
m.ChunkSize = 0
|
||||||
for shift := uint(0); ; shift += 7 {
|
for shift := uint(0); ; shift += 7 {
|
||||||
if shift >= 64 {
|
if shift >= 64 {
|
||||||
return ErrIntOverflow
|
return protohelpers.ErrIntOverflow
|
||||||
}
|
}
|
||||||
if iNdEx >= l {
|
if iNdEx >= l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -257,7 +240,7 @@ func (m *Header) UnmarshalVT(dAtA []byte) error {
|
||||||
var byteLen int
|
var byteLen int
|
||||||
for shift := uint(0); ; shift += 7 {
|
for shift := uint(0); ; shift += 7 {
|
||||||
if shift >= 64 {
|
if shift >= 64 {
|
||||||
return ErrIntOverflow
|
return protohelpers.ErrIntOverflow
|
||||||
}
|
}
|
||||||
if iNdEx >= l {
|
if iNdEx >= l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -270,11 +253,11 @@ func (m *Header) UnmarshalVT(dAtA []byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if byteLen < 0 {
|
if byteLen < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
postIndex := iNdEx + byteLen
|
postIndex := iNdEx + byteLen
|
||||||
if postIndex < 0 {
|
if postIndex < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -291,7 +274,7 @@ func (m *Header) UnmarshalVT(dAtA []byte) error {
|
||||||
var byteLen int
|
var byteLen int
|
||||||
for shift := uint(0); ; shift += 7 {
|
for shift := uint(0); ; shift += 7 {
|
||||||
if shift >= 64 {
|
if shift >= 64 {
|
||||||
return ErrIntOverflow
|
return protohelpers.ErrIntOverflow
|
||||||
}
|
}
|
||||||
if iNdEx >= l {
|
if iNdEx >= l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -304,11 +287,11 @@ func (m *Header) UnmarshalVT(dAtA []byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if byteLen < 0 {
|
if byteLen < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
postIndex := iNdEx + byteLen
|
postIndex := iNdEx + byteLen
|
||||||
if postIndex < 0 {
|
if postIndex < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -325,7 +308,7 @@ func (m *Header) UnmarshalVT(dAtA []byte) error {
|
||||||
var byteLen int
|
var byteLen int
|
||||||
for shift := uint(0); ; shift += 7 {
|
for shift := uint(0); ; shift += 7 {
|
||||||
if shift >= 64 {
|
if shift >= 64 {
|
||||||
return ErrIntOverflow
|
return protohelpers.ErrIntOverflow
|
||||||
}
|
}
|
||||||
if iNdEx >= l {
|
if iNdEx >= l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -338,11 +321,11 @@ func (m *Header) UnmarshalVT(dAtA []byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if byteLen < 0 {
|
if byteLen < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
postIndex := iNdEx + byteLen
|
postIndex := iNdEx + byteLen
|
||||||
if postIndex < 0 {
|
if postIndex < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -359,7 +342,7 @@ func (m *Header) UnmarshalVT(dAtA []byte) error {
|
||||||
var msglen int
|
var msglen int
|
||||||
for shift := uint(0); ; shift += 7 {
|
for shift := uint(0); ; shift += 7 {
|
||||||
if shift >= 64 {
|
if shift >= 64 {
|
||||||
return ErrIntOverflow
|
return protohelpers.ErrIntOverflow
|
||||||
}
|
}
|
||||||
if iNdEx >= l {
|
if iNdEx >= l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -372,11 +355,11 @@ func (m *Header) UnmarshalVT(dAtA []byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if msglen < 0 {
|
if msglen < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
postIndex := iNdEx + msglen
|
postIndex := iNdEx + msglen
|
||||||
if postIndex < 0 {
|
if postIndex < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -388,12 +371,12 @@ func (m *Header) UnmarshalVT(dAtA []byte) error {
|
||||||
iNdEx = postIndex
|
iNdEx = postIndex
|
||||||
default:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
skippy, err := skip(dAtA[iNdEx:])
|
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
if (iNdEx + skippy) > l {
|
if (iNdEx + skippy) > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -416,7 +399,7 @@ func (m *WrappedKey) UnmarshalVT(dAtA []byte) error {
|
||||||
var wire uint64
|
var wire uint64
|
||||||
for shift := uint(0); ; shift += 7 {
|
for shift := uint(0); ; shift += 7 {
|
||||||
if shift >= 64 {
|
if shift >= 64 {
|
||||||
return ErrIntOverflow
|
return protohelpers.ErrIntOverflow
|
||||||
}
|
}
|
||||||
if iNdEx >= l {
|
if iNdEx >= l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -444,7 +427,7 @@ func (m *WrappedKey) UnmarshalVT(dAtA []byte) error {
|
||||||
var byteLen int
|
var byteLen int
|
||||||
for shift := uint(0); ; shift += 7 {
|
for shift := uint(0); ; shift += 7 {
|
||||||
if shift >= 64 {
|
if shift >= 64 {
|
||||||
return ErrIntOverflow
|
return protohelpers.ErrIntOverflow
|
||||||
}
|
}
|
||||||
if iNdEx >= l {
|
if iNdEx >= l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -457,11 +440,11 @@ func (m *WrappedKey) UnmarshalVT(dAtA []byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if byteLen < 0 {
|
if byteLen < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
postIndex := iNdEx + byteLen
|
postIndex := iNdEx + byteLen
|
||||||
if postIndex < 0 {
|
if postIndex < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -478,7 +461,7 @@ func (m *WrappedKey) UnmarshalVT(dAtA []byte) error {
|
||||||
var byteLen int
|
var byteLen int
|
||||||
for shift := uint(0); ; shift += 7 {
|
for shift := uint(0); ; shift += 7 {
|
||||||
if shift >= 64 {
|
if shift >= 64 {
|
||||||
return ErrIntOverflow
|
return protohelpers.ErrIntOverflow
|
||||||
}
|
}
|
||||||
if iNdEx >= l {
|
if iNdEx >= l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -491,11 +474,11 @@ func (m *WrappedKey) UnmarshalVT(dAtA []byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if byteLen < 0 {
|
if byteLen < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
postIndex := iNdEx + byteLen
|
postIndex := iNdEx + byteLen
|
||||||
if postIndex < 0 {
|
if postIndex < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -507,12 +490,12 @@ func (m *WrappedKey) UnmarshalVT(dAtA []byte) error {
|
||||||
iNdEx = postIndex
|
iNdEx = postIndex
|
||||||
default:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
skippy, err := skip(dAtA[iNdEx:])
|
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||||
return ErrInvalidLength
|
return protohelpers.ErrInvalidLength
|
||||||
}
|
}
|
||||||
if (iNdEx + skippy) > l {
|
if (iNdEx + skippy) > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
|
@ -527,88 +510,3 @@ func (m *WrappedKey) UnmarshalVT(dAtA []byte) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func skip(dAtA []byte) (n int, err error) {
|
|
||||||
l := len(dAtA)
|
|
||||||
iNdEx := 0
|
|
||||||
depth := 0
|
|
||||||
for iNdEx < l {
|
|
||||||
var wire uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflow
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
wire |= (uint64(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wireType := int(wire & 0x7)
|
|
||||||
switch wireType {
|
|
||||||
case 0:
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflow
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
iNdEx++
|
|
||||||
if dAtA[iNdEx-1] < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
iNdEx += 8
|
|
||||||
case 2:
|
|
||||||
var length int
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflow
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
length |= (int(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if length < 0 {
|
|
||||||
return 0, ErrInvalidLength
|
|
||||||
}
|
|
||||||
iNdEx += length
|
|
||||||
case 3:
|
|
||||||
depth++
|
|
||||||
case 4:
|
|
||||||
if depth == 0 {
|
|
||||||
return 0, ErrUnexpectedEndOfGroup
|
|
||||||
}
|
|
||||||
depth--
|
|
||||||
case 5:
|
|
||||||
iNdEx += 4
|
|
||||||
default:
|
|
||||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
|
||||||
}
|
|
||||||
if iNdEx < 0 {
|
|
||||||
return 0, ErrInvalidLength
|
|
||||||
}
|
|
||||||
if depth == 0 {
|
|
||||||
return iNdEx, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrInvalidLength = fmt.Errorf("proto: negative length found during unmarshaling")
|
|
||||||
ErrIntOverflow = fmt.Errorf("proto: integer overflow")
|
|
||||||
ErrUnexpectedEndOfGroup = fmt.Errorf("proto: unexpected end of group")
|
|
||||||
)
|
|
||||||
|
|
54
mk-rel.sh
Executable file
54
mk-rel.sh
Executable file
|
@ -0,0 +1,54 @@
|
||||||
|
#! /usr/bin/env bash
|
||||||
|
|
||||||
|
Z=`basename $0`
|
||||||
|
die() {
|
||||||
|
echo "$Z: $@" 1>&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
warn() {
|
||||||
|
echo "$Z: $@" 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
case $BASH_VERSION in
|
||||||
|
4.*|5.*) ;;
|
||||||
|
|
||||||
|
*) die "I need bash 4.x to run!"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
Rel=$PWD/releases
|
||||||
|
Bindir=$Rel/bin
|
||||||
|
mkdir -p $Bindir || die "can't make $Bindir"
|
||||||
|
|
||||||
|
pkgit() {
|
||||||
|
local os=$1
|
||||||
|
local cpu=$2
|
||||||
|
local rev=$3
|
||||||
|
local arch="$os-$cpu"
|
||||||
|
local tgz="$Rel/sigtool-${rev}_${arch}.tar.gz"
|
||||||
|
local bindir=$Bindir/$arch
|
||||||
|
local bin=sigtool
|
||||||
|
|
||||||
|
if [ "$os" = "windows" ]; then
|
||||||
|
bin=${bin}.exe
|
||||||
|
fi
|
||||||
|
|
||||||
|
./build -V $rev -b $Bindir -s -a $arch || die "can't build $arch"
|
||||||
|
(cd $bindir && tar cf - $bin) | gzip -9 > $tgz || die "can't tar $tgz"
|
||||||
|
}
|
||||||
|
|
||||||
|
xrev=$(git describe --always --dirty --abbrev=12) || exit 1
|
||||||
|
if echo $xrev | grep -q dirty; then
|
||||||
|
die "won't build releases; repo dirty!"
|
||||||
|
true
|
||||||
|
fi
|
||||||
|
|
||||||
|
os="linux windows openbsd darwin"
|
||||||
|
arch="amd64 arm64"
|
||||||
|
|
||||||
|
for xx in $os; do
|
||||||
|
for yy in $arch; do
|
||||||
|
pkgit $xx $yy $xrev
|
||||||
|
done
|
||||||
|
done
|
3
renovate.json
Normal file
3
renovate.json
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
|
||||||
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
[](https://godoc.org/github.com/opencoff/sigtool/sign)
|
[](https://godoc.org/git.rgst.io/homelab/sigtool/v3/sign)
|
||||||
|
|
||||||
# sigtool/sign - Ed25519 signature calculation and verification
|
# sigtool/sign - Ed25519 signature calculation and verification
|
||||||
|
|
||||||
This is a small library that makes it easier to create and serialize Ed25519 keys, and sign,
|
This is a small library that makes it easier to create and serialize Ed25519 keys, and sign,
|
||||||
verify files using those keys. The library uses mmap(2) to read and process very large files.
|
verify files using those keys. The library uses mmap(2) to read and process very large files.
|
||||||
|
|
||||||
The companion program [sigtool](https://github.com/opencoff/sigtool) uses this library.
|
The companion program [sigtool](https://git.rgst.io/homelab/sigtool/v3) uses this library.
|
||||||
## License
|
## License
|
||||||
GPL v2.0
|
GPL v2.0
|
||||||
|
|
|
@ -70,13 +70,14 @@ import (
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/crypto/curve25519"
|
|
||||||
"golang.org/x/crypto/hkdf"
|
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/opencoff/sigtool/internal/pb"
|
"golang.org/x/crypto/curve25519"
|
||||||
|
"golang.org/x/crypto/hkdf"
|
||||||
|
|
||||||
|
"git.rgst.io/homelab/sigtool/v3/internal/pb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Encryption chunk size = 4MB
|
// Encryption chunk size = 4MB
|
||||||
|
|
|
@ -16,8 +16,8 @@ package sign
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/opencoff/go-fio"
|
||||||
"github.com/opencoff/go-mmap"
|
"github.com/opencoff/go-mmap"
|
||||||
"github.com/opencoff/go-utils"
|
|
||||||
"hash"
|
"hash"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
@ -26,11 +26,19 @@ import (
|
||||||
// Does MORE than ioutil.WriteFile() - in that it doesn't trash the
|
// Does MORE than ioutil.WriteFile() - in that it doesn't trash the
|
||||||
// existing file with an incomplete write.
|
// existing file with an incomplete write.
|
||||||
func writeFile(fn string, b []byte, ovwrite bool, mode uint32) error {
|
func writeFile(fn string, b []byte, ovwrite bool, mode uint32) error {
|
||||||
sf, err := utils.NewSafeFile(fn, ovwrite, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.FileMode(mode))
|
var opts uint32
|
||||||
|
if ovwrite {
|
||||||
|
opts |= fio.OPT_OVERWRITE
|
||||||
|
}
|
||||||
|
sf, err := fio.NewSafeFile(fn, opts, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.FileMode(mode))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
sf.Write(b)
|
defer sf.Abort()
|
||||||
|
if _, err = sf.Write(b); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return sf.Close()
|
return sf.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
42
sign/keys.go
42
sign/keys.go
|
@ -30,8 +30,9 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
Ed "crypto/ed25519"
|
Ed "crypto/ed25519"
|
||||||
|
|
||||||
"golang.org/x/crypto/scrypt"
|
"golang.org/x/crypto/scrypt"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Private Ed25519 key
|
// Private Ed25519 key
|
||||||
|
@ -179,14 +180,14 @@ func makePrivateKeyFromBytes(sk *PrivateKey, buf []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Make a private key from 64-bytes of extended Ed25519 key
|
// Make a private key from 64-bytes of extended Ed25519 key
|
||||||
func PrivateKeyFromBytes(buf []byte) (*PrivateKey, error) {
|
func PrivateKeyFromBytes(buf []byte) (*PrivateKey, error) {
|
||||||
var sk PrivateKey
|
var sk PrivateKey
|
||||||
|
if err := makePrivateKeyFromBytes(&sk, buf); err != nil {
|
||||||
return makePrivateKeyFromBytes(&sk, buf)
|
return nil, err
|
||||||
|
}
|
||||||
|
return &sk, nil
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// Given a secret key, return the corresponding Public Key
|
// Given a secret key, return the corresponding Public Key
|
||||||
func (sk *PrivateKey) PublicKey() *PublicKey {
|
func (sk *PrivateKey) PublicKey() *PublicKey {
|
||||||
|
@ -369,6 +370,29 @@ func MakePublicKey(yml []byte) (*PublicKey, error) {
|
||||||
return &pk, nil
|
return &pk, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make a public key from a string
|
||||||
|
func MakePublicKeyFromString(s string) (*PublicKey, error) {
|
||||||
|
// first try to decode it as a openssh key
|
||||||
|
if pk2, err := parseEncPubKey([]byte(s), "command-line-pk"); err == nil {
|
||||||
|
return pk2, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now try to decode as an sigtool key
|
||||||
|
b64 := base64.StdEncoding.DecodeString
|
||||||
|
|
||||||
|
pkb, err := b64(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var pk PublicKey
|
||||||
|
err = makePublicKeyFromBytes(&pk, pkb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pk, nil
|
||||||
|
}
|
||||||
|
|
||||||
func makePublicKeyFromBytes(pk *PublicKey, b []byte) error {
|
func makePublicKeyFromBytes(pk *PublicKey, b []byte) error {
|
||||||
if len(b) != 32 {
|
if len(b) != 32 {
|
||||||
return fmt.Errorf("public key is malformed (len %d!)", len(b))
|
return fmt.Errorf("public key is malformed (len %d!)", len(b))
|
||||||
|
@ -381,14 +405,14 @@ func makePublicKeyFromBytes(pk *PublicKey, b []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Make a public key from a byte string
|
// Make a public key from a byte string
|
||||||
func PublicKeyFromBytes(b []byte) (*PublicKey, error) {
|
func PublicKeyFromBytes(b []byte) (*PublicKey, error) {
|
||||||
var pk PublicKey
|
var pk PublicKey
|
||||||
|
if err := makePublicKeyFromBytes(&pk, b); err != nil {
|
||||||
makePublicKeyFromBytes(&pk, b)
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pk, nil
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// Serialize a PublicKey into file 'fn' with a human readable 'comment'.
|
// Serialize a PublicKey into file 'fn' with a human readable 'comment'.
|
||||||
// If 'ovwrite' is true, overwrite the file if it exists.
|
// If 'ovwrite' is true, overwrite the file if it exists.
|
||||||
|
|
|
@ -27,7 +27,8 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
Ed "crypto/ed25519"
|
Ed "crypto/ed25519"
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// An Ed25519 Signature
|
// An Ed25519 Signature
|
||||||
|
|
360
sigtool.go
360
sigtool.go
|
@ -1,360 +0,0 @@
|
||||||
// sigtool.go -- Tool to generate, manage Ed25519 keys and
|
|
||||||
// signatures.
|
|
||||||
//
|
|
||||||
// (c) 2016 Sudhi Herle <sudhi@herle.net>
|
|
||||||
//
|
|
||||||
// Licensing Terms: GPLv2
|
|
||||||
//
|
|
||||||
// If you need a commercial license for this work, please contact
|
|
||||||
// the author.
|
|
||||||
//
|
|
||||||
// This software does not come with any express or implied
|
|
||||||
// warranty; it is provided "as is". No claim is made to its
|
|
||||||
// suitability for any purpose.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/opencoff/go-utils"
|
|
||||||
flag "github.com/opencoff/pflag"
|
|
||||||
"github.com/opencoff/sigtool/sign"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Z string = path.Base(os.Args[0])
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
var ver, help, debug bool
|
|
||||||
|
|
||||||
mf := flag.NewFlagSet(Z, flag.ExitOnError)
|
|
||||||
mf.SetInterspersed(false)
|
|
||||||
mf.BoolVarP(&ver, "version", "v", false, "Show version info and exit")
|
|
||||||
mf.BoolVarP(&help, "help", "h", false, "Show help info exit")
|
|
||||||
mf.BoolVarP(&debug, "debug", "", false, "Enable debug mode")
|
|
||||||
mf.Parse(os.Args[1:])
|
|
||||||
|
|
||||||
if ver {
|
|
||||||
fmt.Printf("%s - %s [%s; %s]\n", Z, ProductVersion, RepoVersion, Buildtime)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if help {
|
|
||||||
usage(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
args := mf.Args()
|
|
||||||
if len(args) < 1 {
|
|
||||||
Die("Insufficient arguments. Try '%s -h'", Z)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmds := map[string]func(args []string){
|
|
||||||
"generate": gen,
|
|
||||||
"sign": signify,
|
|
||||||
"verify": verify,
|
|
||||||
"encrypt": encrypt,
|
|
||||||
"decrypt": decrypt,
|
|
||||||
|
|
||||||
"help": func(_ []string) {
|
|
||||||
usage(0)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
words := make([]string, 0, len(cmds))
|
|
||||||
for k := range cmds {
|
|
||||||
words = append(words, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
ab := utils.Abbrev(words)
|
|
||||||
canon, ok := ab[strings.ToLower(args[0])]
|
|
||||||
if !ok {
|
|
||||||
Die("Unknown command %s", args[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := cmds[canon]
|
|
||||||
if cmd == nil {
|
|
||||||
Die("can't map command %s", canon)
|
|
||||||
}
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
sign.Debug(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd(args[1:])
|
|
||||||
|
|
||||||
// always call Exit so that at-exit handlers are called.
|
|
||||||
Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the generate command
|
|
||||||
func gen(args []string) {
|
|
||||||
|
|
||||||
var nopw, help, force bool
|
|
||||||
var comment string
|
|
||||||
var envpw string
|
|
||||||
|
|
||||||
fs := flag.NewFlagSet("generate", flag.ExitOnError)
|
|
||||||
fs.BoolVarP(&help, "help", "h", false, "Show this help and exit")
|
|
||||||
fs.BoolVarP(&nopw, "no-password", "", false, "Don't ask for a password for the private key")
|
|
||||||
fs.StringVarP(&comment, "comment", "c", "", "Use `C` as the text comment for the keys")
|
|
||||||
fs.StringVarP(&envpw, "env-password", "E", "", "Use passphrase from environment variable `E`")
|
|
||||||
fs.BoolVarP(&force, "overwrite", "", false, "Overwrite the output file if it exists")
|
|
||||||
|
|
||||||
fs.Parse(args)
|
|
||||||
|
|
||||||
if help {
|
|
||||||
fs.SetOutput(os.Stdout)
|
|
||||||
fmt.Printf(`%s generate|gen|g [options] file-prefix
|
|
||||||
|
|
||||||
Generate a new Ed25519 public+private key pair and write public key to
|
|
||||||
FILE-PREFIX.pub and private key to FILE-PREFIX.key.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
`, Z)
|
|
||||||
fs.PrintDefaults()
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
args = fs.Args()
|
|
||||||
if len(args) < 1 {
|
|
||||||
Die("Insufficient arguments to 'generate'. Try '%s generate -h' ..", Z)
|
|
||||||
}
|
|
||||||
|
|
||||||
bn := args[0]
|
|
||||||
|
|
||||||
pkn := fmt.Sprintf("%s.pub", path.Clean(bn))
|
|
||||||
skn := fmt.Sprintf("%s.key", path.Clean(bn))
|
|
||||||
|
|
||||||
if !force {
|
|
||||||
if exists(pkn) || exists(skn) {
|
|
||||||
Die("Public/Private key files (%s, %s) exist. won't overwrite!", skn, pkn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
var pw []byte
|
|
||||||
|
|
||||||
if !nopw {
|
|
||||||
var pws string
|
|
||||||
if len(envpw) > 0 {
|
|
||||||
pws = os.Getenv(envpw)
|
|
||||||
} else {
|
|
||||||
pws, err = utils.Askpass("Enter passphrase for private key", true)
|
|
||||||
if err != nil {
|
|
||||||
Die("%s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pw = []byte(pws)
|
|
||||||
}
|
|
||||||
|
|
||||||
sk, err := sign.NewPrivateKey()
|
|
||||||
if err != nil {
|
|
||||||
Die("%s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = sk.Serialize(skn, comment, force, pw); err != nil {
|
|
||||||
Die("%s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pk := sk.PublicKey()
|
|
||||||
if err = pk.Serialize(pkn, comment, force); err != nil {
|
|
||||||
Die("%s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the 'sign' command.
|
|
||||||
func signify(args []string) {
|
|
||||||
var nopw, help, force bool
|
|
||||||
var output string
|
|
||||||
var envpw string
|
|
||||||
|
|
||||||
fs := flag.NewFlagSet("sign", flag.ExitOnError)
|
|
||||||
fs.BoolVarP(&help, "help", "h", false, "Show this help and exit")
|
|
||||||
fs.BoolVarP(&nopw, "no-password", "", false, "Don't ask for a password for the private key")
|
|
||||||
fs.StringVarP(&envpw, "env-password", "E", "", "Use passphrase from environment variable `E`")
|
|
||||||
fs.StringVarP(&output, "output", "o", "", "Write signature to file `F`")
|
|
||||||
fs.BoolVarP(&force, "overwrite", "", false, "Overwrite previous signature file if it exists")
|
|
||||||
|
|
||||||
fs.Parse(args)
|
|
||||||
|
|
||||||
if help {
|
|
||||||
fs.SetOutput(os.Stdout)
|
|
||||||
fmt.Printf(`%s sign|s [options] privkey file
|
|
||||||
|
|
||||||
Sign FILE with a Ed25519 private key PRIVKEY and write signature to FILE.sig
|
|
||||||
|
|
||||||
Options:
|
|
||||||
`, Z)
|
|
||||||
fs.PrintDefaults()
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
args = fs.Args()
|
|
||||||
if len(args) < 2 {
|
|
||||||
Die("Insufficient arguments to 'sign'. Try '%s sign -h' ..", Z)
|
|
||||||
}
|
|
||||||
|
|
||||||
kn := args[0]
|
|
||||||
fn := args[1]
|
|
||||||
outf := fmt.Sprintf("%s.sig", fn)
|
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if len(output) > 0 {
|
|
||||||
outf = output
|
|
||||||
}
|
|
||||||
|
|
||||||
var fd io.WriteCloser = os.Stdout
|
|
||||||
|
|
||||||
if outf != "-" {
|
|
||||||
sf, err := utils.NewSafeFile(outf, force, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
|
|
||||||
if err != nil {
|
|
||||||
Die("can't create sig file: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// we unlink and remove temp on any error
|
|
||||||
AtExit(sf.Abort)
|
|
||||||
defer sf.Abort()
|
|
||||||
fd = sf
|
|
||||||
}
|
|
||||||
|
|
||||||
sk, err := sign.ReadPrivateKey(kn, func() ([]byte, error) {
|
|
||||||
if nopw {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var pws string
|
|
||||||
if len(envpw) > 0 {
|
|
||||||
pws = os.Getenv(envpw)
|
|
||||||
} else {
|
|
||||||
pws, err = utils.Askpass("Enter passphrase for private key", false)
|
|
||||||
if err != nil {
|
|
||||||
Die("%s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return []byte(pws), nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
Die("%s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sig, err := sk.SignFile(fn)
|
|
||||||
if err != nil {
|
|
||||||
Die("%s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sigbytes, err := sig.MarshalBinary(fmt.Sprintf("input=%s", fn))
|
|
||||||
fd.Write(sigbytes)
|
|
||||||
fd.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify signature on a given file
|
|
||||||
func verify(args []string) {
|
|
||||||
var help, quiet bool
|
|
||||||
|
|
||||||
fs := flag.NewFlagSet("verify", flag.ExitOnError)
|
|
||||||
fs.BoolVarP(&help, "help", "h", false, "Show this help and exit")
|
|
||||||
fs.BoolVarP(&quiet, "quiet", "q", false, "Don't show any output; exit with status code only")
|
|
||||||
|
|
||||||
fs.Parse(args)
|
|
||||||
|
|
||||||
if help {
|
|
||||||
fs.SetOutput(os.Stdout)
|
|
||||||
fmt.Printf(`%s verify|v [options] pubkey sig file
|
|
||||||
|
|
||||||
Verify an Ed25519 signature in SIG of FILE using a public key PUBKEY.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
`, Z)
|
|
||||||
fs.PrintDefaults()
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
args = fs.Args()
|
|
||||||
if len(args) < 3 {
|
|
||||||
Die("Insufficient arguments to 'verify'. Try '%s verify -h' ..", Z)
|
|
||||||
}
|
|
||||||
|
|
||||||
pn := args[0]
|
|
||||||
sn := args[1]
|
|
||||||
fn := args[2]
|
|
||||||
|
|
||||||
sig, err := sign.ReadSignature(sn)
|
|
||||||
if err != nil {
|
|
||||||
Die("Can't read signature '%s': %s", sn, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pk, err := sign.ReadPublicKey(pn)
|
|
||||||
if err != nil {
|
|
||||||
Die("%s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !sig.IsPKMatch(pk) {
|
|
||||||
Die("Wrong public key '%s' for verifying '%s'", pn, sn)
|
|
||||||
}
|
|
||||||
|
|
||||||
ok, err := pk.VerifyFile(fn, sig)
|
|
||||||
if err != nil {
|
|
||||||
Die("%s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
exit := 0
|
|
||||||
if !ok {
|
|
||||||
exit = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if !quiet {
|
|
||||||
if ok {
|
|
||||||
fmt.Printf("%s: Signature %s verified\n", fn, sn)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("%s: Signature %s verification failure\n", fn, sn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Exit(exit)
|
|
||||||
}
|
|
||||||
|
|
||||||
func usage(c int) {
|
|
||||||
x := fmt.Sprintf(`%s is a tool to generate, sign and verify files with Ed25519 signatures.
|
|
||||||
|
|
||||||
Usage: %s [global-options] command [options] arg [args..]
|
|
||||||
|
|
||||||
Global options:
|
|
||||||
-h, --help Show help and exit
|
|
||||||
-v, --version Show version info and exit
|
|
||||||
--debug Enable debug (DANGEROUS)
|
|
||||||
|
|
||||||
Commands:
|
|
||||||
generate, g Generate a new Ed25519 keypair
|
|
||||||
sign, s Sign a file with a private key
|
|
||||||
verify, v Verify a signature against a file and a public key
|
|
||||||
encrypt, e Encrypt an input file to one or more recipients
|
|
||||||
decrypt, d Decrypt a file with a private key
|
|
||||||
`, Z, Z)
|
|
||||||
|
|
||||||
os.Stdout.Write([]byte(x))
|
|
||||||
os.Exit(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return true if $bn.key or $bn.pub exist; false otherwise
|
|
||||||
func exists(nm string) bool {
|
|
||||||
if _, err := os.Stat(nm); err == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// This will be filled in by "build"
|
|
||||||
var RepoVersion string = "UNDEFINED"
|
|
||||||
var Buildtime string = "UNDEFINED"
|
|
||||||
var ProductVersion string = "UNDEFINED"
|
|
||||||
|
|
||||||
// vim: ft=go:sw=8:ts=8:noexpandtab:tw=98:
|
|
|
@ -20,9 +20,10 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"git.rgst.io/homelab/sigtool/v3/sign"
|
||||||
|
"github.com/opencoff/go-fio"
|
||||||
"github.com/opencoff/go-utils"
|
"github.com/opencoff/go-utils"
|
||||||
flag "github.com/opencoff/pflag"
|
flag "github.com/opencoff/pflag"
|
||||||
"github.com/opencoff/sigtool/sign"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// sigtool encrypt [-i|--identity my.key] to.pub [to.pub] [ssh.pub] inputfile|- [-o output]
|
// sigtool encrypt [-i|--identity my.key] to.pub [to.pub] [ssh.pub] inputfile|- [-o output]
|
||||||
|
@ -140,7 +141,11 @@ func encrypt(args []string) {
|
||||||
mode = ist.Mode()
|
mode = ist.Mode()
|
||||||
}
|
}
|
||||||
|
|
||||||
sf, err := utils.NewSafeFile(outfile, force, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
|
var opts uint32
|
||||||
|
if force {
|
||||||
|
opts |= fio.OPT_OVERWRITE
|
||||||
|
}
|
||||||
|
sf, err := fio.NewSafeFile(outfile, opts, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Die("%s", err)
|
Die("%s", err)
|
||||||
}
|
}
|
||||||
|
@ -302,7 +307,11 @@ func decrypt(args []string) {
|
||||||
mode = ist.Mode()
|
mode = ist.Mode()
|
||||||
}
|
}
|
||||||
|
|
||||||
sf, err := utils.NewSafeFile(outfile, force, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
|
var opts uint32
|
||||||
|
if force {
|
||||||
|
opts |= fio.OPT_OVERWRITE
|
||||||
|
}
|
||||||
|
sf, err := fio.NewSafeFile(outfile, opts, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Die("%s", err)
|
Die("%s", err)
|
||||||
}
|
}
|
100
src/gen.go
Normal file
100
src/gen.go
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
// gen.go -- generate keys
|
||||||
|
//
|
||||||
|
// (c) 2016 Sudhi Herle <sudhi@herle.net>
|
||||||
|
//
|
||||||
|
// Licensing Terms: GPLv2
|
||||||
|
//
|
||||||
|
// If you need a commercial license for this work, please contact
|
||||||
|
// the author.
|
||||||
|
//
|
||||||
|
// This software does not come with any express or implied
|
||||||
|
// warranty; it is provided "as is". No claim is made to its
|
||||||
|
// suitability for any purpose.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"git.rgst.io/homelab/sigtool/v3/sign"
|
||||||
|
"github.com/opencoff/go-utils"
|
||||||
|
flag "github.com/opencoff/pflag"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Run the generate command
|
||||||
|
func gen(args []string) {
|
||||||
|
var nopw, help, force bool
|
||||||
|
var comment string
|
||||||
|
var envpw string
|
||||||
|
|
||||||
|
fs := flag.NewFlagSet("generate", flag.ExitOnError)
|
||||||
|
fs.BoolVarP(&help, "help", "h", false, "Show this help and exit")
|
||||||
|
fs.BoolVarP(&nopw, "no-password", "", false, "Don't ask for a password for the private key")
|
||||||
|
fs.StringVarP(&comment, "comment", "c", "", "Use `C` as the text comment for the keys")
|
||||||
|
fs.StringVarP(&envpw, "env-password", "E", "", "Use passphrase from environment variable `E`")
|
||||||
|
fs.BoolVarP(&force, "overwrite", "", false, "Overwrite the output file if it exists")
|
||||||
|
|
||||||
|
fs.Parse(args)
|
||||||
|
|
||||||
|
if help {
|
||||||
|
fs.SetOutput(os.Stdout)
|
||||||
|
fmt.Printf(`%s generate|gen|g [options] file-prefix
|
||||||
|
|
||||||
|
Generate a new Ed25519 public+private key pair and write public key to
|
||||||
|
FILE-PREFIX.pub and private key to FILE-PREFIX.key.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
`, Z)
|
||||||
|
fs.PrintDefaults()
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
args = fs.Args()
|
||||||
|
if len(args) < 1 {
|
||||||
|
Die("Insufficient arguments to 'generate'. Try '%s generate -h' ..", Z)
|
||||||
|
}
|
||||||
|
|
||||||
|
bn := args[0]
|
||||||
|
|
||||||
|
pkn := fmt.Sprintf("%s.pub", path.Clean(bn))
|
||||||
|
skn := fmt.Sprintf("%s.key", path.Clean(bn))
|
||||||
|
|
||||||
|
if !force {
|
||||||
|
if exists(pkn) || exists(skn) {
|
||||||
|
Die("Public/Private key files (%s, %s) exist. won't overwrite!", skn, pkn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var pw []byte
|
||||||
|
|
||||||
|
if !nopw {
|
||||||
|
var pws string
|
||||||
|
if len(envpw) > 0 {
|
||||||
|
pws = os.Getenv(envpw)
|
||||||
|
} else {
|
||||||
|
pws, err = utils.Askpass("Enter passphrase for private key", true)
|
||||||
|
if err != nil {
|
||||||
|
Die("%s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pw = []byte(pws)
|
||||||
|
}
|
||||||
|
|
||||||
|
sk, err := sign.NewPrivateKey()
|
||||||
|
if err != nil {
|
||||||
|
Die("%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = sk.Serialize(skn, comment, force, pw); err != nil {
|
||||||
|
Die("%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pk := sk.PublicKey()
|
||||||
|
if err = pk.Serialize(pkn, comment, force); err != nil {
|
||||||
|
Die("%s", err)
|
||||||
|
}
|
||||||
|
}
|
116
src/sign.go
Normal file
116
src/sign.go
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
// sign.go -- 'sign' command implementation
|
||||||
|
//
|
||||||
|
// (c) 2016 Sudhi Herle <sudhi@herle.net>
|
||||||
|
//
|
||||||
|
// Licensing Terms: GPLv2
|
||||||
|
//
|
||||||
|
// If you need a commercial license for this work, please contact
|
||||||
|
// the author.
|
||||||
|
//
|
||||||
|
// This software does not come with any express or implied
|
||||||
|
// warranty; it is provided "as is". No claim is made to its
|
||||||
|
// suitability for any purpose.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.rgst.io/homelab/sigtool/v3/sign"
|
||||||
|
"github.com/opencoff/go-fio"
|
||||||
|
"github.com/opencoff/go-utils"
|
||||||
|
flag "github.com/opencoff/pflag"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Run the 'sign' command.
|
||||||
|
func signify(args []string) {
|
||||||
|
var nopw, help, force bool
|
||||||
|
var output string
|
||||||
|
var envpw string
|
||||||
|
|
||||||
|
fs := flag.NewFlagSet("sign", flag.ExitOnError)
|
||||||
|
fs.BoolVarP(&help, "help", "h", false, "Show this help and exit")
|
||||||
|
fs.BoolVarP(&nopw, "no-password", "", false, "Don't ask for a password for the private key")
|
||||||
|
fs.StringVarP(&envpw, "env-password", "E", "", "Use passphrase from environment variable `E`")
|
||||||
|
fs.StringVarP(&output, "output", "o", "", "Write signature to file `F`")
|
||||||
|
fs.BoolVarP(&force, "overwrite", "", false, "Overwrite previous signature file if it exists")
|
||||||
|
|
||||||
|
fs.Parse(args)
|
||||||
|
|
||||||
|
if help {
|
||||||
|
fs.SetOutput(os.Stdout)
|
||||||
|
fmt.Printf(`%s sign|s [options] privkey file
|
||||||
|
|
||||||
|
Sign FILE with a Ed25519 private key PRIVKEY and write signature to FILE.sig
|
||||||
|
|
||||||
|
Options:
|
||||||
|
`, Z)
|
||||||
|
fs.PrintDefaults()
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
args = fs.Args()
|
||||||
|
if len(args) < 2 {
|
||||||
|
Die("Insufficient arguments to 'sign'. Try '%s sign -h' ..", Z)
|
||||||
|
}
|
||||||
|
|
||||||
|
kn := args[0]
|
||||||
|
fn := args[1]
|
||||||
|
outf := fmt.Sprintf("%s.sig", fn)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if len(output) > 0 {
|
||||||
|
outf = output
|
||||||
|
}
|
||||||
|
|
||||||
|
var fd io.WriteCloser = os.Stdout
|
||||||
|
|
||||||
|
if outf != "-" {
|
||||||
|
var opts uint32
|
||||||
|
if force {
|
||||||
|
opts |= fio.OPT_OVERWRITE
|
||||||
|
}
|
||||||
|
sf, err := fio.NewSafeFile(outf, opts, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
Die("can't create sig file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// we unlink and remove temp on any error
|
||||||
|
AtExit(sf.Abort)
|
||||||
|
defer sf.Abort()
|
||||||
|
fd = sf
|
||||||
|
}
|
||||||
|
|
||||||
|
sk, err := sign.ReadPrivateKey(kn, func() ([]byte, error) {
|
||||||
|
if nopw {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var pws string
|
||||||
|
if len(envpw) > 0 {
|
||||||
|
pws = os.Getenv(envpw)
|
||||||
|
} else {
|
||||||
|
pws, err = utils.Askpass("Enter passphrase for private key", false)
|
||||||
|
if err != nil {
|
||||||
|
Die("%s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte(pws), nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
Die("%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := sk.SignFile(fn)
|
||||||
|
if err != nil {
|
||||||
|
Die("%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sigbytes, err := sig.MarshalBinary(fmt.Sprintf("input=%s", fn))
|
||||||
|
fd.Write(sigbytes)
|
||||||
|
fd.Close()
|
||||||
|
}
|
129
src/sigtool.go
Normal file
129
src/sigtool.go
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
// sigtool.go -- Tool to generate, manage Ed25519 keys and
|
||||||
|
// signatures.
|
||||||
|
//
|
||||||
|
// (c) 2016 Sudhi Herle <sudhi@herle.net>
|
||||||
|
//
|
||||||
|
// Licensing Terms: GPLv2
|
||||||
|
//
|
||||||
|
// If you need a commercial license for this work, please contact
|
||||||
|
// the author.
|
||||||
|
//
|
||||||
|
// This software does not come with any express or implied
|
||||||
|
// warranty; it is provided "as is". No claim is made to its
|
||||||
|
// suitability for any purpose.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.rgst.io/homelab/sigtool/v3/sign"
|
||||||
|
"github.com/opencoff/go-utils"
|
||||||
|
flag "github.com/opencoff/pflag"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Z string = path.Base(os.Args[0])
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var ver, help, debug bool
|
||||||
|
|
||||||
|
mf := flag.NewFlagSet(Z, flag.ExitOnError)
|
||||||
|
mf.SetInterspersed(false)
|
||||||
|
mf.BoolVarP(&ver, "version", "v", false, "Show version info and exit")
|
||||||
|
mf.BoolVarP(&help, "help", "h", false, "Show help info exit")
|
||||||
|
mf.BoolVarP(&debug, "debug", "", false, "Enable debug mode")
|
||||||
|
mf.Parse(os.Args[1:])
|
||||||
|
|
||||||
|
if ver {
|
||||||
|
fmt.Printf("%s - %s [%s]\n", Z, ProductVersion, RepoVersion)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if help {
|
||||||
|
usage(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
args := mf.Args()
|
||||||
|
if len(args) < 1 {
|
||||||
|
Die("Insufficient arguments. Try '%s -h'", Z)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmds := map[string]func(args []string){
|
||||||
|
"generate": gen,
|
||||||
|
"sign": signify,
|
||||||
|
"verify": verify,
|
||||||
|
"encrypt": encrypt,
|
||||||
|
"decrypt": decrypt,
|
||||||
|
|
||||||
|
"help": func(_ []string) {
|
||||||
|
usage(0)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
words := make([]string, 0, len(cmds))
|
||||||
|
for k := range cmds {
|
||||||
|
words = append(words, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
ab := utils.Abbrev(words)
|
||||||
|
canon, ok := ab[strings.ToLower(args[0])]
|
||||||
|
if !ok {
|
||||||
|
Die("Unknown command %s", args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := cmds[canon]
|
||||||
|
if cmd == nil {
|
||||||
|
Die("can't map command %s", canon)
|
||||||
|
}
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
sign.Debug(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd(args[1:])
|
||||||
|
|
||||||
|
// always call Exit so that at-exit handlers are called.
|
||||||
|
Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify signature on a given file
|
||||||
|
|
||||||
|
func usage(c int) {
|
||||||
|
x := fmt.Sprintf(`%s is a tool to generate, sign and verify files with Ed25519 signatures.
|
||||||
|
|
||||||
|
Usage: %s [global-options] command [options] arg [args..]
|
||||||
|
|
||||||
|
Global options:
|
||||||
|
-h, --help Show help and exit
|
||||||
|
-v, --version Show version info and exit
|
||||||
|
--debug Enable debug (DANGEROUS)
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
generate, g Generate a new Ed25519 keypair
|
||||||
|
sign, s Sign a file with a private key
|
||||||
|
verify, v Verify a signature against a file and a public key
|
||||||
|
encrypt, e Encrypt an input file to one or more recipients
|
||||||
|
decrypt, d Decrypt a file with a private key
|
||||||
|
`, Z, Z)
|
||||||
|
|
||||||
|
os.Stdout.Write([]byte(x))
|
||||||
|
os.Exit(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if $bn.key or $bn.pub exist; false otherwise
|
||||||
|
func exists(nm string) bool {
|
||||||
|
if _, err := os.Stat(nm); err == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will be filled in by "build"
|
||||||
|
var RepoVersion string = "UNDEFINED"
|
||||||
|
var ProductVersion string = "UNDEFINED"
|
||||||
|
|
||||||
|
// vim: ft=go:sw=8:ts=8:noexpandtab:tw=98:
|
96
src/verify.go
Normal file
96
src/verify.go
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
// verify.go -- Verify signatures
|
||||||
|
//
|
||||||
|
// (c) 2016 Sudhi Herle <sudhi@herle.net>
|
||||||
|
//
|
||||||
|
// Licensing Terms: GPLv2
|
||||||
|
//
|
||||||
|
// If you need a commercial license for this work, please contact
|
||||||
|
// the author.
|
||||||
|
//
|
||||||
|
// This software does not come with any express or implied
|
||||||
|
// warranty; it is provided "as is". No claim is made to its
|
||||||
|
// suitability for any purpose.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.rgst.io/homelab/sigtool/v3/sign"
|
||||||
|
flag "github.com/opencoff/pflag"
|
||||||
|
)
|
||||||
|
|
||||||
|
func verify(args []string) {
|
||||||
|
var help, quiet bool
|
||||||
|
|
||||||
|
fs := flag.NewFlagSet("verify", flag.ExitOnError)
|
||||||
|
fs.BoolVarP(&help, "help", "h", false, "Show this help and exit")
|
||||||
|
fs.BoolVarP(&quiet, "quiet", "q", false, "Don't show any output; exit with status code only")
|
||||||
|
|
||||||
|
fs.Parse(args)
|
||||||
|
|
||||||
|
if help {
|
||||||
|
fs.SetOutput(os.Stdout)
|
||||||
|
fmt.Printf(`%s verify|v [options] pubkey sig file
|
||||||
|
|
||||||
|
Verify an Ed25519 signature in SIG of FILE using a public key PUBKEY.
|
||||||
|
The pubkey can be one of:
|
||||||
|
- a file: either OpenSSH ed25519 pubkey or a sigtool pubkey
|
||||||
|
- a string: the raw OpenSSH or sigtool pubkey
|
||||||
|
|
||||||
|
%s will first parse it as a string before trying to parse it as a file.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
`, Z, Z)
|
||||||
|
fs.PrintDefaults()
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
args = fs.Args()
|
||||||
|
if len(args) < 3 {
|
||||||
|
Die("Insufficient arguments to 'verify'. Try '%s verify -h' ..", Z)
|
||||||
|
}
|
||||||
|
|
||||||
|
pn := args[0]
|
||||||
|
sn := args[1]
|
||||||
|
fn := args[2]
|
||||||
|
|
||||||
|
// We first try to read the public key as a base64/openssh string
|
||||||
|
pk, err := sign.MakePublicKeyFromString(pn)
|
||||||
|
if err != nil {
|
||||||
|
pk, err = sign.ReadPublicKey(pn)
|
||||||
|
if err != nil {
|
||||||
|
Die("%s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := sign.ReadSignature(sn)
|
||||||
|
if err != nil {
|
||||||
|
Die("Can't read signature '%s': %s", sn, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !sig.IsPKMatch(pk) {
|
||||||
|
Die("Wrong public key '%s' for verifying '%s'", pn, sn)
|
||||||
|
}
|
||||||
|
|
||||||
|
ok, err := pk.VerifyFile(fn, sig)
|
||||||
|
if err != nil {
|
||||||
|
Die("%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
exit := 0
|
||||||
|
if !ok {
|
||||||
|
exit = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if !quiet {
|
||||||
|
if ok {
|
||||||
|
fmt.Printf("%s: Signature %s verified\n", fn, sn)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%s: Signature %s verification failure\n", fn, sn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Exit(exit)
|
||||||
|
}
|
27
tests.sh
27
tests.sh
|
@ -77,26 +77,35 @@ spk2=$ssk2.pub
|
||||||
$keygen -q -C 'ssk1@foo' -t ed25519 -f $ssk1 -N ""
|
$keygen -q -C 'ssk1@foo' -t ed25519 -f $ssk1 -N ""
|
||||||
$keygen -q -C 'ssk2@foo' -t ed25519 -f $ssk2 -N ""
|
$keygen -q -C 'ssk2@foo' -t ed25519 -f $ssk2 -N ""
|
||||||
|
|
||||||
$bin s --no-password $ssk1 -o $sig $0 || die "can't sign with $ssk1"
|
# extract the pk string
|
||||||
$bin v -q $spk1 $sig $0 || die "can't verify with $spk2"
|
spk1_str=$(cat $spk1 | awk '{ print $2 }')
|
||||||
|
|
||||||
$bin e --no-password -o $encout $spk2 $0 || die "can't encrypt to $spk2 with $ssk1"
|
$bin s --no-password $ssk1 -o $sig $0 || die "can't sign with $ssk1"
|
||||||
$bin d --no-password -o $decout $ssk2 $encout || die "can't decrypt with $ssk2"
|
$bin v -q $spk1 $sig $0 || die "can't verify with $spk2"
|
||||||
|
$bin v -q $spk1_str $sig $0 || die "can't verify with $spk2_str"
|
||||||
|
|
||||||
|
$bin e --no-password -o $encout $spk2 $0 || die "can't encrypt to $spk2 with $ssk1"
|
||||||
|
$bin d --no-password -o $decout $ssk2 $encout || die "can't decrypt with $ssk2"
|
||||||
|
|
||||||
# cleanup state
|
# cleanup state
|
||||||
rm -f $sig $encout $decout
|
rm -f $sig $encout $decout
|
||||||
|
|
||||||
|
|
||||||
# generate keys
|
# generate keys
|
||||||
$bin g -E FOO $bn || die "can't gen keypair $pk, $sk"
|
$bin g -E FOO $bn || die "can't gen keypair $pk, $sk"
|
||||||
$bin g -E FOO $bn 2>/dev/null && die "overwrote prev keypair"
|
$bin g -E FOO $bn 2>/dev/null && die "overwrote prev keypair"
|
||||||
$bin g -E FOO --overwrite $bn || die "can't force gen keypair $pk, $sk"
|
$bin g -E FOO --overwrite $bn || die "can't force gen keypair $pk, $sk"
|
||||||
$bin g -E FOO $bn2 || die "can't force gen keypair $pk2, $sk2"
|
$bin g -E FOO $bn2 || die "can't force gen keypair $pk2, $sk2"
|
||||||
|
|
||||||
|
# extract pk string
|
||||||
|
pk_str=$(cat $pk | grep 'pk:' | sed -e 's/^pk: //g')
|
||||||
|
pk2_str=$(cat $pk2 | grep 'pk:' | sed -e 's/^pk: //g')
|
||||||
|
|
||||||
# sign and verify
|
# sign and verify
|
||||||
$bin s -E FOO $sk $0 -o $sig || die "can't sign $0"
|
$bin s -E FOO $sk $0 -o $sig || die "can't sign $0"
|
||||||
$bin v -q $pk $sig $0 || die "can't verify signature of $0"
|
$bin v -q $pk $sig $0 || die "can't verify signature of $0"
|
||||||
$bin v -q $pk2 $sig $0 2>/dev/null && die "bad verification with wrong $pk2"
|
$bin v -q $pk_str $sig $0 || die "can't verify signature of $0"
|
||||||
|
$bin v -q $pk2 $sig $0 2>/dev/null && die "bad verification with wrong $pk2"
|
||||||
|
$bin v -q $pk2_str $sig $0 2>/dev/null && die "bad verification with wrong $pk2"
|
||||||
|
|
||||||
# encrypt/decrypt
|
# encrypt/decrypt
|
||||||
$bin e -E FOO -o $encout $pk2 $0 || die "can't encrypt to $pk2"
|
$bin e -E FOO -o $encout $pk2 $0 || die "can't encrypt to $pk2"
|
||||||
|
@ -106,7 +115,7 @@ cmp -s $decout $0 || die "decrypted file mismatch with $0"
|
||||||
# now with sender verification
|
# now with sender verification
|
||||||
$bin e -E FOO --overwrite -o $encout -s $sk $pk2 $0 || die "can't sender-encrypt to $pk2"
|
$bin e -E FOO --overwrite -o $encout -s $sk $pk2 $0 || die "can't sender-encrypt to $pk2"
|
||||||
$bin d -E FOO --overwrite -o $decout -v $pk $sk2 $encout || die "can't decrypt with $sk2"
|
$bin d -E FOO --overwrite -o $decout -v $pk $sk2 $encout || die "can't decrypt with $sk2"
|
||||||
cmp -s $decout $0 || die "decrypted file mismatch with $0"
|
cmp -s $decout $0 || die "decrypted file mismatch with $0"
|
||||||
|
|
||||||
# Only delete if everything worked
|
# Only delete if everything worked
|
||||||
echo "$Z: All tests pass!"
|
echo "$Z: All tests pass!"
|
||||||
|
|
Loading…
Add table
Reference in a new issue