update vendor keybase/go-crypto (#10234)
parent
86fdba177a
commit
bfd62b6f01
2
go.mod
2
go.mod
|
@ -58,7 +58,7 @@ require (
|
|||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/joho/godotenv v1.3.0 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20170619183022-cd60e84ee657
|
||||
github.com/keybase/go-crypto v0.0.0-20170605145657-00ac4db533f6
|
||||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
|
||||
github.com/klauspost/compress v1.9.2
|
||||
github.com/lafriks/xormstore v1.3.2
|
||||
github.com/lib/pq v1.2.0
|
||||
|
|
7
go.sum
7
go.sum
|
@ -9,8 +9,6 @@ cloud.google.com/go v0.45.0 h1:bALuGBSgE+BD4rxsopAYlqjcwqcQtye6pWG4bC3N/k0=
|
|||
cloud.google.com/go v0.45.0/go.mod h1:452BcPOeI9AZfbvDw0Tbo7D32wA+WX9WME8AZwMEDZU=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
gitea.com/lunny/levelqueue v0.1.0 h1:7wMk0VH6mvKN6vZEZCy9nUDgRmdPLgeNrm1NkW8EHNk=
|
||||
gitea.com/lunny/levelqueue v0.1.0/go.mod h1:G7hVb908t0Bl0uk7zGSg14fyzNtxgtD9Shf04wkMK7s=
|
||||
gitea.com/lunny/levelqueue v0.2.0 h1:lR/5EAwQtFcn5YvPEkNMw0p9pAy2/O2nSP5ImECLA2E=
|
||||
gitea.com/lunny/levelqueue v0.2.0/go.mod h1:G7hVb908t0Bl0uk7zGSg14fyzNtxgtD9Shf04wkMK7s=
|
||||
gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b h1:vXt85uYV17KURaUlhU7v4GbCShkqRZDSfo0TkC0YCjQ=
|
||||
|
@ -340,8 +338,8 @@ github.com/kballard/go-shellquote v0.0.0-20170619183022-cd60e84ee657 h1:vE7J1m7c
|
|||
github.com/kballard/go-shellquote v0.0.0-20170619183022-cd60e84ee657/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/keybase/go-crypto v0.0.0-20170605145657-00ac4db533f6 h1:9mszGwKDxHEY2cy+9XxCQKWIfkGPSAEFrcN8ghzyAKg=
|
||||
github.com/keybase/go-crypto v0.0.0-20170605145657-00ac4db533f6/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
|
||||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4 h1:cTxwSmnaqLoo+4tLukHoB9iqHOu3LmLhRmgUxZo6Vp4=
|
||||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.9.2 h1:LfVyl+ZlLlLDeQ/d2AqfGIIH4qEDu0Ed2S5GyhCWIWY=
|
||||
|
@ -508,7 +506,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
|||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/src-d/enry v1.7.3 h1:jG2fmEaQaURh0qqU/sn82BRzVa6d4EVHJIw6gc98bak=
|
||||
github.com/src-d/enry/v2 v2.1.0 h1:z1L8t+B8bh3mmjPkJrgOTnVRpFGmTPJsplHX9wAn6BI=
|
||||
github.com/src-d/enry/v2 v2.1.0/go.mod h1:qQeCMRwzMF3ckeGr+h0tJLdxXnq+NVZsIDMELj0t028=
|
||||
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
|
||||
// OpenPGP cipher.
|
||||
package cast5
|
||||
package cast5 // import "github.com/keybase/go-crypto/cast5"
|
||||
|
||||
import "errors"
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||
|
||||
#define REDMASK51 0x0007FFFFFFFFFFFF
|
|
@ -3,12 +3,12 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
|
||||
GLOBL ·REDMASK51(SB), 8, $8
|
||||
// These constants cannot be encoded in non-MOVQ immediates.
|
||||
// We access them directly from memory instead.
|
||||
|
||||
DATA ·_121666_213(SB)/8, $996687872
|
||||
GLOBL ·_121666_213(SB), 8, $8
|
||||
|
|
|
@ -2,87 +2,64 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
// func cswap(inout *[5]uint64, v uint64)
|
||||
// func cswap(inout *[4][5]uint64, v uint64)
|
||||
TEXT ·cswap(SB),7,$0
|
||||
MOVQ inout+0(FP),DI
|
||||
MOVQ v+8(FP),SI
|
||||
|
||||
CMPQ SI,$1
|
||||
MOVQ 0(DI),SI
|
||||
MOVQ 80(DI),DX
|
||||
MOVQ 8(DI),CX
|
||||
MOVQ 88(DI),R8
|
||||
MOVQ SI,R9
|
||||
CMOVQEQ DX,SI
|
||||
CMOVQEQ R9,DX
|
||||
MOVQ CX,R9
|
||||
CMOVQEQ R8,CX
|
||||
CMOVQEQ R9,R8
|
||||
MOVQ SI,0(DI)
|
||||
MOVQ DX,80(DI)
|
||||
MOVQ CX,8(DI)
|
||||
MOVQ R8,88(DI)
|
||||
MOVQ 16(DI),SI
|
||||
MOVQ 96(DI),DX
|
||||
MOVQ 24(DI),CX
|
||||
MOVQ 104(DI),R8
|
||||
MOVQ SI,R9
|
||||
CMOVQEQ DX,SI
|
||||
CMOVQEQ R9,DX
|
||||
MOVQ CX,R9
|
||||
CMOVQEQ R8,CX
|
||||
CMOVQEQ R9,R8
|
||||
MOVQ SI,16(DI)
|
||||
MOVQ DX,96(DI)
|
||||
MOVQ CX,24(DI)
|
||||
MOVQ R8,104(DI)
|
||||
MOVQ 32(DI),SI
|
||||
MOVQ 112(DI),DX
|
||||
MOVQ 40(DI),CX
|
||||
MOVQ 120(DI),R8
|
||||
MOVQ SI,R9
|
||||
CMOVQEQ DX,SI
|
||||
CMOVQEQ R9,DX
|
||||
MOVQ CX,R9
|
||||
CMOVQEQ R8,CX
|
||||
CMOVQEQ R9,R8
|
||||
MOVQ SI,32(DI)
|
||||
MOVQ DX,112(DI)
|
||||
MOVQ CX,40(DI)
|
||||
MOVQ R8,120(DI)
|
||||
MOVQ 48(DI),SI
|
||||
MOVQ 128(DI),DX
|
||||
MOVQ 56(DI),CX
|
||||
MOVQ 136(DI),R8
|
||||
MOVQ SI,R9
|
||||
CMOVQEQ DX,SI
|
||||
CMOVQEQ R9,DX
|
||||
MOVQ CX,R9
|
||||
CMOVQEQ R8,CX
|
||||
CMOVQEQ R9,R8
|
||||
MOVQ SI,48(DI)
|
||||
MOVQ DX,128(DI)
|
||||
MOVQ CX,56(DI)
|
||||
MOVQ R8,136(DI)
|
||||
MOVQ 64(DI),SI
|
||||
MOVQ 144(DI),DX
|
||||
MOVQ 72(DI),CX
|
||||
MOVQ 152(DI),R8
|
||||
MOVQ SI,R9
|
||||
CMOVQEQ DX,SI
|
||||
CMOVQEQ R9,DX
|
||||
MOVQ CX,R9
|
||||
CMOVQEQ R8,CX
|
||||
CMOVQEQ R9,R8
|
||||
MOVQ SI,64(DI)
|
||||
MOVQ DX,144(DI)
|
||||
MOVQ CX,72(DI)
|
||||
MOVQ R8,152(DI)
|
||||
MOVQ DI,AX
|
||||
MOVQ SI,DX
|
||||
SUBQ $1, SI
|
||||
NOTQ SI
|
||||
MOVQ SI, X15
|
||||
PSHUFD $0x44, X15, X15
|
||||
|
||||
MOVOU 0(DI), X0
|
||||
MOVOU 16(DI), X2
|
||||
MOVOU 32(DI), X4
|
||||
MOVOU 48(DI), X6
|
||||
MOVOU 64(DI), X8
|
||||
MOVOU 80(DI), X1
|
||||
MOVOU 96(DI), X3
|
||||
MOVOU 112(DI), X5
|
||||
MOVOU 128(DI), X7
|
||||
MOVOU 144(DI), X9
|
||||
|
||||
MOVO X1, X10
|
||||
MOVO X3, X11
|
||||
MOVO X5, X12
|
||||
MOVO X7, X13
|
||||
MOVO X9, X14
|
||||
|
||||
PXOR X0, X10
|
||||
PXOR X2, X11
|
||||
PXOR X4, X12
|
||||
PXOR X6, X13
|
||||
PXOR X8, X14
|
||||
PAND X15, X10
|
||||
PAND X15, X11
|
||||
PAND X15, X12
|
||||
PAND X15, X13
|
||||
PAND X15, X14
|
||||
PXOR X10, X0
|
||||
PXOR X10, X1
|
||||
PXOR X11, X2
|
||||
PXOR X11, X3
|
||||
PXOR X12, X4
|
||||
PXOR X12, X5
|
||||
PXOR X13, X6
|
||||
PXOR X13, X7
|
||||
PXOR X14, X8
|
||||
PXOR X14, X9
|
||||
|
||||
MOVOU X0, 0(DI)
|
||||
MOVOU X2, 16(DI)
|
||||
MOVOU X4, 32(DI)
|
||||
MOVOU X6, 48(DI)
|
||||
MOVOU X8, 64(DI)
|
||||
MOVOU X1, 80(DI)
|
||||
MOVOU X3, 96(DI)
|
||||
MOVOU X5, 112(DI)
|
||||
MOVOU X7, 128(DI)
|
||||
MOVOU X9, 144(DI)
|
||||
RET
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// We have a implementation in amd64 assembly so this code is only run on
|
||||
// We have an implementation in amd64 assembly so this code is only run on
|
||||
// non-amd64 platforms. The amd64 assembly does not support gccgo.
|
||||
// +build !amd64 gccgo appengine
|
||||
|
||||
package curve25519
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// This code is a port of the public domain, "ref10" implementation of
|
||||
// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
|
||||
|
||||
|
@ -50,17 +54,11 @@ func feCopy(dst, src *fieldElement) {
|
|||
//
|
||||
// Preconditions: b in {0,1}.
|
||||
func feCSwap(f, g *fieldElement, b int32) {
|
||||
var x fieldElement
|
||||
b = -b
|
||||
for i := range x {
|
||||
x[i] = b & (f[i] ^ g[i])
|
||||
}
|
||||
|
||||
for i := range f {
|
||||
f[i] ^= x[i]
|
||||
}
|
||||
for i := range g {
|
||||
g[i] ^= x[i]
|
||||
t := b & (f[i] ^ g[i])
|
||||
f[i] ^= t
|
||||
g[i] ^= t
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,12 +73,7 @@ func load3(in []byte) int64 {
|
|||
|
||||
// load4 reads a 32-bit, little-endian value from in.
|
||||
func load4(in []byte) int64 {
|
||||
var r int64
|
||||
r = int64(in[0])
|
||||
r |= int64(in[1]) << 8
|
||||
r |= int64(in[2]) << 16
|
||||
r |= int64(in[3]) << 24
|
||||
return r
|
||||
return int64(binary.LittleEndian.Uint32(in))
|
||||
}
|
||||
|
||||
func feFromBytes(dst *fieldElement, src *[32]byte) {
|
||||
|
|
|
@ -16,19 +16,30 @@ func copyReverse(dst []byte, src []byte) {
|
|||
// Curve 25519 multiplication functions expect scalars in reverse
|
||||
// order than PGP. To keep the curve25519Curve type consistent
|
||||
// with other curves, we reverse it here.
|
||||
for i, j := 0, len(src)-1; j >= 0; i, j = i+1, j-1 {
|
||||
for i, j := 0, len(src)-1; j >= 0 && i < len(dst); i, j = i+1, j-1 {
|
||||
dst[i] = src[j]
|
||||
}
|
||||
}
|
||||
|
||||
func copyTruncate(dst []byte, src []byte) {
|
||||
lenDst, lenSrc := len(dst), len(src)
|
||||
if lenDst == lenSrc {
|
||||
copy(dst, src)
|
||||
} else if lenDst > lenSrc {
|
||||
copy(dst[lenDst-lenSrc:lenDst], src)
|
||||
} else if lenDst < lenSrc {
|
||||
copy(dst, src[:lenDst])
|
||||
}
|
||||
}
|
||||
|
||||
func (cv25519Curve) ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int) {
|
||||
// Assume y1 is 0 with cv25519.
|
||||
var dst [32]byte
|
||||
var x1Bytes [32]byte
|
||||
var scalarBytes [32]byte
|
||||
|
||||
copy(x1Bytes[:], x1.Bytes()[:32])
|
||||
copyReverse(scalarBytes[:], scalar[:32])
|
||||
copyTruncate(x1Bytes[:], x1.Bytes())
|
||||
copyReverse(scalarBytes[:], scalar)
|
||||
|
||||
scalarMult(&dst, &scalarBytes, &x1Bytes)
|
||||
|
||||
|
@ -63,7 +74,7 @@ func (cv25519Curve) MarshalType40(x, y *big.Int) []byte {
|
|||
ret[0] = 0x40
|
||||
|
||||
xBytes := x.Bytes()
|
||||
copy(ret[1+byteLen-len(xBytes):], xBytes)
|
||||
copyTruncate(ret[1:], xBytes)
|
||||
return ret
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package curve25519 provides an implementation of scalar multiplication on
|
||||
// the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html
|
||||
package curve25519
|
||||
// the elliptic curve known as curve25519. See https://cr.yp.to/ecdh.html
|
||||
package curve25519 // import "github.com/keybase/go-crypto/curve25519"
|
||||
|
||||
// basePoint is the x coordinate of the generator of the curve.
|
||||
var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
|
|
|
@ -3,33 +3,22 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func freeze(inout *[5]uint64)
|
||||
TEXT ·freeze(SB),7,$96-8
|
||||
TEXT ·freeze(SB),7,$0-8
|
||||
MOVQ inout+0(FP), DI
|
||||
|
||||
MOVQ SP,R11
|
||||
MOVQ $31,CX
|
||||
NOTQ CX
|
||||
ANDQ CX,SP
|
||||
ADDQ $32,SP
|
||||
|
||||
MOVQ R11,0(SP)
|
||||
MOVQ R12,8(SP)
|
||||
MOVQ R13,16(SP)
|
||||
MOVQ R14,24(SP)
|
||||
MOVQ R15,32(SP)
|
||||
MOVQ BX,40(SP)
|
||||
MOVQ BP,48(SP)
|
||||
MOVQ 0(DI),SI
|
||||
MOVQ 8(DI),DX
|
||||
MOVQ 16(DI),CX
|
||||
MOVQ 24(DI),R8
|
||||
MOVQ 32(DI),R9
|
||||
MOVQ ·REDMASK51(SB),AX
|
||||
MOVQ $REDMASK51,AX
|
||||
MOVQ AX,R10
|
||||
SUBQ $18,R10
|
||||
MOVQ $3,R11
|
||||
|
@ -81,14 +70,4 @@ REDUCELOOP:
|
|||
MOVQ CX,16(DI)
|
||||
MOVQ R8,24(DI)
|
||||
MOVQ R9,32(DI)
|
||||
MOVQ 0(SP),R11
|
||||
MOVQ 8(SP),R12
|
||||
MOVQ 16(SP),R13
|
||||
MOVQ 24(SP),R14
|
||||
MOVQ 32(SP),R15
|
||||
MOVQ 40(SP),BX
|
||||
MOVQ 48(SP),BP
|
||||
MOVQ R11,SP
|
||||
MOVQ DI,AX
|
||||
MOVQ SI,DX
|
||||
RET
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,40 +3,28 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func mul(dest, a, b *[5]uint64)
|
||||
TEXT ·mul(SB),0,$128-24
|
||||
TEXT ·mul(SB),0,$16-24
|
||||
MOVQ dest+0(FP), DI
|
||||
MOVQ a+8(FP), SI
|
||||
MOVQ b+16(FP), DX
|
||||
|
||||
MOVQ SP,R11
|
||||
MOVQ $31,CX
|
||||
NOTQ CX
|
||||
ANDQ CX,SP
|
||||
ADDQ $32,SP
|
||||
|
||||
MOVQ R11,0(SP)
|
||||
MOVQ R12,8(SP)
|
||||
MOVQ R13,16(SP)
|
||||
MOVQ R14,24(SP)
|
||||
MOVQ R15,32(SP)
|
||||
MOVQ BX,40(SP)
|
||||
MOVQ BP,48(SP)
|
||||
MOVQ DI,56(SP)
|
||||
MOVQ DX,CX
|
||||
MOVQ 24(SI),DX
|
||||
IMUL3Q $19,DX,AX
|
||||
MOVQ AX,64(SP)
|
||||
MOVQ AX,0(SP)
|
||||
MULQ 16(CX)
|
||||
MOVQ AX,R8
|
||||
MOVQ DX,R9
|
||||
MOVQ 32(SI),DX
|
||||
IMUL3Q $19,DX,AX
|
||||
MOVQ AX,72(SP)
|
||||
MOVQ AX,8(SP)
|
||||
MULQ 8(CX)
|
||||
ADDQ AX,R8
|
||||
ADCQ DX,R9
|
||||
|
@ -111,11 +99,11 @@ TEXT ·mul(SB),0,$128-24
|
|||
MULQ 8(CX)
|
||||
ADDQ AX,BX
|
||||
ADCQ DX,BP
|
||||
MOVQ 64(SP),AX
|
||||
MOVQ 0(SP),AX
|
||||
MULQ 24(CX)
|
||||
ADDQ AX,R10
|
||||
ADCQ DX,R11
|
||||
MOVQ 64(SP),AX
|
||||
MOVQ 0(SP),AX
|
||||
MULQ 32(CX)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
|
@ -123,19 +111,19 @@ TEXT ·mul(SB),0,$128-24
|
|||
MULQ 0(CX)
|
||||
ADDQ AX,BX
|
||||
ADCQ DX,BP
|
||||
MOVQ 72(SP),AX
|
||||
MOVQ 8(SP),AX
|
||||
MULQ 16(CX)
|
||||
ADDQ AX,R10
|
||||
ADCQ DX,R11
|
||||
MOVQ 72(SP),AX
|
||||
MOVQ 8(SP),AX
|
||||
MULQ 24(CX)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ 72(SP),AX
|
||||
MOVQ 8(SP),AX
|
||||
MULQ 32(CX)
|
||||
ADDQ AX,R14
|
||||
ADCQ DX,R15
|
||||
MOVQ ·REDMASK51(SB),SI
|
||||
MOVQ $REDMASK51,SI
|
||||
SHLQ $13,R9:R8
|
||||
ANDQ SI,R8
|
||||
SHLQ $13,R11:R10
|
||||
|
@ -178,14 +166,4 @@ TEXT ·mul(SB),0,$128-24
|
|||
MOVQ R9,16(DI)
|
||||
MOVQ AX,24(DI)
|
||||
MOVQ R10,32(DI)
|
||||
MOVQ 0(SP),R11
|
||||
MOVQ 8(SP),R12
|
||||
MOVQ 16(SP),R13
|
||||
MOVQ 24(SP),R14
|
||||
MOVQ 32(SP),R15
|
||||
MOVQ 40(SP),BX
|
||||
MOVQ 48(SP),BP
|
||||
MOVQ R11,SP
|
||||
MOVQ DI,AX
|
||||
MOVQ SI,DX
|
||||
RET
|
||||
|
|
|
@ -3,28 +3,17 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func square(out, in *[5]uint64)
|
||||
TEXT ·square(SB),7,$96-16
|
||||
TEXT ·square(SB),7,$0-16
|
||||
MOVQ out+0(FP), DI
|
||||
MOVQ in+8(FP), SI
|
||||
|
||||
MOVQ SP,R11
|
||||
MOVQ $31,CX
|
||||
NOTQ CX
|
||||
ANDQ CX,SP
|
||||
ADDQ $32, SP
|
||||
|
||||
MOVQ R11,0(SP)
|
||||
MOVQ R12,8(SP)
|
||||
MOVQ R13,16(SP)
|
||||
MOVQ R14,24(SP)
|
||||
MOVQ R15,32(SP)
|
||||
MOVQ BX,40(SP)
|
||||
MOVQ BP,48(SP)
|
||||
MOVQ 0(SI),AX
|
||||
MULQ 0(SI)
|
||||
MOVQ AX,CX
|
||||
|
@ -97,7 +86,7 @@ TEXT ·square(SB),7,$96-16
|
|||
MULQ 32(SI)
|
||||
ADDQ AX,R13
|
||||
ADCQ DX,R14
|
||||
MOVQ ·REDMASK51(SB),SI
|
||||
MOVQ $REDMASK51,SI
|
||||
SHLQ $13,R8:CX
|
||||
ANDQ SI,CX
|
||||
SHLQ $13,R10:R9
|
||||
|
@ -140,14 +129,4 @@ TEXT ·square(SB),7,$96-16
|
|||
MOVQ R9,16(DI)
|
||||
MOVQ AX,24(DI)
|
||||
MOVQ R10,32(DI)
|
||||
MOVQ 0(SP),R11
|
||||
MOVQ 8(SP),R12
|
||||
MOVQ 16(SP),R13
|
||||
MOVQ 24(SP),R14
|
||||
MOVQ 32(SP),R15
|
||||
MOVQ 40(SP),BX
|
||||
MOVQ 48(SP),BP
|
||||
MOVQ R11,SP
|
||||
MOVQ DI,AX
|
||||
MOVQ SI,DX
|
||||
RET
|
||||
|
|
|
@ -3,20 +3,23 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package ed25519 implements the Ed25519 signature algorithm. See
|
||||
// http://ed25519.cr.yp.to/.
|
||||
// https://ed25519.cr.yp.to/.
|
||||
//
|
||||
// These functions are also compatible with the “Ed25519” function defined in
|
||||
// https://tools.ietf.org/html/draft-irtf-cfrg-eddsa-05.
|
||||
// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
|
||||
// representation includes a public key suffix to make multiple signing
|
||||
// operations with the same key more efficient. This package refers to the RFC
|
||||
// 8032 private key as the “seed”.
|
||||
package ed25519
|
||||
|
||||
// This code is a port of the public domain, “ref10” implementation of ed25519
|
||||
// from SUPERCOP.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
cryptorand "crypto/rand"
|
||||
"crypto/sha512"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"io"
|
||||
"strconv"
|
||||
|
@ -31,6 +34,8 @@ const (
|
|||
PrivateKeySize = 64
|
||||
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
|
||||
SignatureSize = 64
|
||||
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
|
||||
SeedSize = 32
|
||||
)
|
||||
|
||||
// PublicKey is the type of Ed25519 public keys.
|
||||
|
@ -46,6 +51,15 @@ func (priv PrivateKey) Public() crypto.PublicKey {
|
|||
return PublicKey(publicKey)
|
||||
}
|
||||
|
||||
// Seed returns the private key seed corresponding to priv. It is provided for
|
||||
// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
|
||||
// in this package.
|
||||
func (priv PrivateKey) Seed() []byte {
|
||||
seed := make([]byte, SeedSize)
|
||||
copy(seed, priv[:32])
|
||||
return seed
|
||||
}
|
||||
|
||||
// Sign signs the given message with priv.
|
||||
// Ed25519 performs two passes over messages to be signed and therefore cannot
|
||||
// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
|
||||
|
@ -61,19 +75,33 @@ func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOp
|
|||
|
||||
// GenerateKey generates a public/private key pair using entropy from rand.
|
||||
// If rand is nil, crypto/rand.Reader will be used.
|
||||
func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) {
|
||||
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
|
||||
if rand == nil {
|
||||
rand = cryptorand.Reader
|
||||
}
|
||||
|
||||
privateKey = make([]byte, PrivateKeySize)
|
||||
publicKey = make([]byte, PublicKeySize)
|
||||
_, err = io.ReadFull(rand, privateKey[:32])
|
||||
if err != nil {
|
||||
seed := make([]byte, SeedSize)
|
||||
if _, err := io.ReadFull(rand, seed); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
digest := sha512.Sum512(privateKey[:32])
|
||||
privateKey := NewKeyFromSeed(seed)
|
||||
publicKey := make([]byte, PublicKeySize)
|
||||
copy(publicKey, privateKey[32:])
|
||||
|
||||
return publicKey, privateKey, nil
|
||||
}
|
||||
|
||||
// NewKeyFromSeed calculates a private key from a seed. It will panic if
|
||||
// len(seed) is not SeedSize. This function is provided for interoperability
|
||||
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
|
||||
// package.
|
||||
func NewKeyFromSeed(seed []byte) PrivateKey {
|
||||
if l := len(seed); l != SeedSize {
|
||||
panic("ed25519: bad seed length: " + strconv.Itoa(l))
|
||||
}
|
||||
|
||||
digest := sha512.Sum512(seed)
|
||||
digest[0] &= 248
|
||||
digest[31] &= 127
|
||||
digest[31] |= 64
|
||||
|
@ -85,10 +113,11 @@ func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, er
|
|||
var publicKeyBytes [32]byte
|
||||
A.ToBytes(&publicKeyBytes)
|
||||
|
||||
privateKey := make([]byte, PrivateKeySize)
|
||||
copy(privateKey, seed)
|
||||
copy(privateKey[32:], publicKeyBytes[:])
|
||||
copy(publicKey, publicKeyBytes[:])
|
||||
|
||||
return publicKey, privateKey, nil
|
||||
return privateKey
|
||||
}
|
||||
|
||||
// Sign signs the message with privateKey and returns a signature. It will
|
||||
|
@ -171,11 +200,18 @@ func Verify(publicKey PublicKey, message, sig []byte) bool {
|
|||
edwards25519.ScReduce(&hReduced, &digest)
|
||||
|
||||
var R edwards25519.ProjectiveGroupElement
|
||||
var b [32]byte
|
||||
copy(b[:], sig[32:])
|
||||
edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)
|
||||
var s [32]byte
|
||||
copy(s[:], sig[32:])
|
||||
|
||||
// https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
|
||||
// the range [0, order) in order to prevent signature malleability.
|
||||
if !edwards25519.ScMinimal(&s) {
|
||||
return false
|
||||
}
|
||||
|
||||
edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s)
|
||||
|
||||
var checkR [32]byte
|
||||
R.ToBytes(&checkR)
|
||||
return subtle.ConstantTimeCompare(sig[:32], checkR[:]) == 1
|
||||
return bytes.Equal(sig[:32], checkR[:])
|
||||
}
|
||||
|
|
22
vendor/github.com/keybase/go-crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
22
vendor/github.com/keybase/go-crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
|
@ -4,6 +4,8 @@
|
|||
|
||||
package edwards25519
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
// This code is a port of the public domain, “ref10” implementation of ed25519
|
||||
// from SUPERCOP.
|
||||
|
||||
|
@ -1769,3 +1771,23 @@ func ScReduce(out *[32]byte, s *[64]byte) {
|
|||
out[30] = byte(s11 >> 9)
|
||||
out[31] = byte(s11 >> 17)
|
||||
}
|
||||
|
||||
// order is the order of Curve25519 in little-endian form.
|
||||
var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000}
|
||||
|
||||
// ScMinimal returns true if the given scalar is less than the order of the
|
||||
// curve.
|
||||
func ScMinimal(scalar *[32]byte) bool {
|
||||
for i := 3; ; i-- {
|
||||
v := binary.LittleEndian.Uint64(scalar[i*8:])
|
||||
if v > order[i] {
|
||||
return false
|
||||
} else if v < order[i] {
|
||||
break
|
||||
} else if i == 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
@ -89,49 +90,113 @@ func (l *lineReader) Read(p []byte) (n int, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
line, _, err := l.in.ReadLine()
|
||||
line, isPrefix, err := l.in.ReadLine()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Entry-level cleanup, just trim spaces.
|
||||
line = bytes.TrimFunc(line, ourIsSpace)
|
||||
|
||||
if len(line) == 5 && line[0] == '=' {
|
||||
// This is the checksum line
|
||||
lineWithChecksum := false
|
||||
foldedChecksum := false
|
||||
if !isPrefix && len(line) >= 5 && line[len(line)-5] == '=' && line[len(line)-4] != '=' {
|
||||
// This is the checksum line. Checksum should appear on separate line,
|
||||
// but some bundles don't have a newline between main payload and the
|
||||
// checksum, and we try to support that.
|
||||
|
||||
// `=` is not a base64 character with the exception of padding, and the
|
||||
// padding can only be 2 characters long at most ("=="), so we can
|
||||
// safely assume that 5 characters starting with `=` at the end of the
|
||||
// line can't be a valid ending of a base64 stream. In other words, `=`
|
||||
// at position len-5 in base64 stream can never be a valid part of that
|
||||
// stream.
|
||||
|
||||
// Checksum can never appear if isPrefix is true - that is, when
|
||||
// ReadLine returned non-final part of some line because it was longer
|
||||
// than its buffer.
|
||||
|
||||
if l.crc != nil {
|
||||
// Error out early if there are multiple checksums.
|
||||
return 0, ArmorCorrupt
|
||||
}
|
||||
|
||||
var expectedBytes [3]byte
|
||||
var m int
|
||||
m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:])
|
||||
if m != 3 || err != nil {
|
||||
return
|
||||
m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[len(line)-4:])
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error decoding CRC: %s", err.Error())
|
||||
} else if m != 3 {
|
||||
return 0, fmt.Errorf("error decoding CRC: wrong size CRC")
|
||||
}
|
||||
|
||||
crc := uint32(expectedBytes[0])<<16 |
|
||||
uint32(expectedBytes[1])<<8 |
|
||||
uint32(expectedBytes[2])
|
||||
l.crc = &crc
|
||||
|
||||
for {
|
||||
line, _, err = l.in.ReadLine()
|
||||
if err != nil && err != io.EOF {
|
||||
return
|
||||
line = line[:len(line)-5]
|
||||
|
||||
lineWithChecksum = true
|
||||
|
||||
// If we've found a checksum but there is still data left, we don't
|
||||
// want to enter the "looking for armor end" loop, we still need to
|
||||
// return the leftover data to the reader.
|
||||
foldedChecksum = len(line) > 0
|
||||
|
||||
// At this point, `line` contains leftover data or "" (if checksum
|
||||
// was on separate line.)
|
||||
}
|
||||
|
||||
expectArmorEnd := false
|
||||
if l.crc != nil && !foldedChecksum {
|
||||
// "looking for armor end" loop
|
||||
|
||||
// We have a checksum, and we are now reading what comes afterwards.
|
||||
// Skip all empty lines until we see something and we except it to be
|
||||
// ArmorEnd at this point.
|
||||
|
||||
// This loop is not entered if there is more data *before* the CRC
|
||||
// suffix (if the CRC is not on separate line).
|
||||
for {
|
||||
if len(strings.TrimSpace(string(line))) > 0 {
|
||||
break
|
||||
}
|
||||
lineWithChecksum = false
|
||||
line, _, err = l.in.ReadLine()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if !bytes.HasPrefix(line, armorEnd) {
|
||||
return 0, ArmorCorrupt
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
l.eof = true
|
||||
return 0, io.EOF
|
||||
}
|
||||
expectArmorEnd = true
|
||||
}
|
||||
|
||||
if bytes.HasPrefix(line, armorEnd) {
|
||||
// Unexpected ending, there was no checksum.
|
||||
l.eof = true
|
||||
l.crc = nil
|
||||
return 0, io.EOF
|
||||
if lineWithChecksum {
|
||||
// ArmorEnd and checksum at the same line?
|
||||
return 0, ArmorCorrupt
|
||||
}
|
||||
l.eof = true
|
||||
return 0, io.EOF
|
||||
} else if expectArmorEnd {
|
||||
// We wanted armorEnd but didn't see one.
|
||||
return 0, ArmorCorrupt
|
||||
}
|
||||
|
||||
// Clean-up line from whitespace to pass it further (to base64
|
||||
// decoder). This is done after test for CRC and test for
|
||||
// armorEnd. Keys that have whitespace in CRC will have CRC
|
||||
// treated as part of the payload and probably fail in base64
|
||||
// reading.
|
||||
line = bytes.Map(func(r rune) rune {
|
||||
if ourIsSpace(r) {
|
||||
return -1
|
||||
}
|
||||
return r
|
||||
}, line)
|
||||
|
||||
n = copy(p, line)
|
||||
bytesToSave := len(line) - n
|
||||
|
|
|
@ -280,3 +280,37 @@ func Unmarshal(curve elliptic.Curve, data []byte) (x, y *big.Int) {
|
|||
|
||||
return elliptic.Unmarshal(curve, data)
|
||||
}
|
||||
|
||||
func GenerateKey(curve elliptic.Curve, random io.Reader) (priv *PrivateKey, err error) {
|
||||
var privBytes []byte
|
||||
var Vx, Vy *big.Int
|
||||
|
||||
if _, ok := curve25519.ToCurve25519(curve); ok {
|
||||
privBytes = make([]byte, 32)
|
||||
_, err = io.ReadFull(random, privBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// NOTE: PGP expect scalars in reverse order than Curve 25519
|
||||
// go library. That's why this trimming is backwards compared
|
||||
// to curve25519.go
|
||||
privBytes[31] &= 248
|
||||
privBytes[0] &= 127
|
||||
privBytes[0] |= 64
|
||||
|
||||
Vx,Vy = curve.ScalarBaseMult(privBytes)
|
||||
} else {
|
||||
privBytes, Vx, Vy, err = elliptic.GenerateKey(curve, random)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
priv = &PrivateKey{}
|
||||
priv.X = new(big.Int).SetBytes(privBytes)
|
||||
priv.PublicKey.Curve = curve
|
||||
priv.PublicKey.X = Vx
|
||||
priv.PublicKey.Y = Vy
|
||||
return priv, nil
|
||||
}
|
||||
|
|
|
@ -70,3 +70,11 @@ type UnknownPacketTypeError uint8
|
|||
func (upte UnknownPacketTypeError) Error() string {
|
||||
return "openpgp: unknown packet type: " + strconv.Itoa(int(upte))
|
||||
}
|
||||
|
||||
// DeprecatedKeyError indicates that the key was read and verified
|
||||
// properly, but uses a deprecated algorithm and can't be used.
|
||||
type DeprecatedKeyError string
|
||||
|
||||
func (d DeprecatedKeyError) Error() string {
|
||||
return "openpgp: key is deprecated: " + string(d)
|
||||
}
|
||||
|
|
|
@ -118,7 +118,8 @@ func (e *Entity) primaryIdentity() *Identity {
|
|||
func (e *Entity) encryptionKey(now time.Time) (Key, bool) {
|
||||
candidateSubkey := -1
|
||||
|
||||
// Iterate the keys to find the newest key
|
||||
// Iterate the keys to find the newest, non-revoked key that can
|
||||
// encrypt.
|
||||
var maxTime time.Time
|
||||
for i, subkey := range e.Subkeys {
|
||||
|
||||
|
@ -172,13 +173,18 @@ func (e *Entity) encryptionKey(now time.Time) (Key, bool) {
|
|||
func (e *Entity) signingKey(now time.Time) (Key, bool) {
|
||||
candidateSubkey := -1
|
||||
|
||||
// Iterate the keys to find the newest, non-revoked key that can
|
||||
// sign.
|
||||
var maxTime time.Time
|
||||
for i, subkey := range e.Subkeys {
|
||||
if (!subkey.Sig.FlagsValid || subkey.Sig.FlagSign) &&
|
||||
subkey.PrivateKey.PrivateKey != nil &&
|
||||
subkey.PublicKey.PubKeyAlgo.CanSign() &&
|
||||
!subkey.Sig.KeyExpired(now) &&
|
||||
subkey.Revocation == nil &&
|
||||
!subkey.Sig.KeyExpired(now) {
|
||||
(maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) {
|
||||
candidateSubkey = i
|
||||
maxTime = subkey.Sig.CreationTime
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -504,7 +510,7 @@ EachPacket:
|
|||
// Only register an identity once we've gotten a valid self-signature.
|
||||
// It's possible therefore for us to throw away `current` in the case
|
||||
// no valid self-signatures were found. That's OK as long as there are
|
||||
// other identies that make sense.
|
||||
// other identities that make sense.
|
||||
//
|
||||
// NOTE! We might later see a revocation for this very same UID, and it
|
||||
// won't be undone. We've preserved this feature from the original
|
||||
|
@ -645,6 +651,15 @@ func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *p
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if subKey.Sig != nil {
|
||||
if err := subKey.PublicKey.ErrorIfDeprecated(); err != nil {
|
||||
// Key passed signature check but is deprecated.
|
||||
subKey.Sig = nil
|
||||
lastErr = err
|
||||
}
|
||||
}
|
||||
|
||||
if subKey.Sig != nil {
|
||||
e.Subkeys = append(e.Subkeys, subKey)
|
||||
} else {
|
||||
|
@ -690,7 +705,7 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
|
|||
}
|
||||
isPrimaryId := true
|
||||
e.Identities[uid.Id] = &Identity{
|
||||
Name: uid.Name,
|
||||
Name: uid.Id,
|
||||
UserId: uid,
|
||||
SelfSignature: &packet.Signature{
|
||||
CreationTime: currentTime,
|
||||
|
@ -705,6 +720,17 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
|
|||
},
|
||||
}
|
||||
|
||||
// If the user passes in a DefaultHash via packet.Config, set the
|
||||
// PreferredHash for the SelfSignature.
|
||||
if config != nil && config.DefaultHash != 0 {
|
||||
e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)}
|
||||
}
|
||||
|
||||
// Likewise for DefaultCipher.
|
||||
if config != nil && config.DefaultCipher != 0 {
|
||||
e.Identities[uid.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(config.DefaultCipher)}
|
||||
}
|
||||
|
||||
e.Subkeys = make([]Subkey, 1)
|
||||
e.Subkeys[0] = Subkey{
|
||||
PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),
|
||||
|
@ -756,10 +782,16 @@ func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Workaround shortcoming of SignKey(), which doesn't work to reverse-sign
|
||||
// sub-signing keys. So if requested, just reuse the signatures already
|
||||
// available to us (if we read this key from a keyring).
|
||||
if e.PrivateKey.PrivateKey != nil && !config.ReuseSignatures() {
|
||||
// If not reusing existing signatures, sign subkey using private key
|
||||
// (subkey binding), but also sign primary key using subkey (primary
|
||||
// key binding) if subkey is used for signing.
|
||||
if subkey.Sig.FlagSign {
|
||||
err = subkey.Sig.CrossSignKey(e.PrimaryKey, subkey.PrivateKey, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
|
||||
if err != nil {
|
||||
return
|
||||
|
|
|
@ -83,6 +83,10 @@ func checksumKeyMaterial(key []byte) uint16 {
|
|||
// private key must have been decrypted first.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
|
||||
if priv == nil || priv.PrivateKey == nil {
|
||||
return errors.InvalidArgumentError("attempting to decrypt with nil PrivateKey")
|
||||
}
|
||||
|
||||
var err error
|
||||
var b []byte
|
||||
|
||||
|
@ -90,7 +94,8 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
|
|||
// padding oracle attacks.
|
||||
switch priv.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
||||
b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1.bytes)
|
||||
k := priv.PrivateKey.(*rsa.PrivateKey)
|
||||
b, err = rsa.DecryptPKCS1v15(config.Random(), k, padToKeySize(&k.PublicKey, e.encryptedMPI1.bytes))
|
||||
case PubKeyAlgoElGamal:
|
||||
c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes)
|
||||
c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes)
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
|
||||
"github.com/keybase/go-crypto/cast5"
|
||||
"github.com/keybase/go-crypto/openpgp/errors"
|
||||
"github.com/keybase/go-crypto/rsa"
|
||||
)
|
||||
|
||||
// readFull is the same as io.ReadFull except that reading zero bytes returns
|
||||
|
@ -415,6 +416,8 @@ const (
|
|||
// RFC 6637, Section 5.
|
||||
PubKeyAlgoECDH PublicKeyAlgorithm = 18
|
||||
PubKeyAlgoECDSA PublicKeyAlgorithm = 19
|
||||
|
||||
PubKeyAlgoBadElGamal PublicKeyAlgorithm = 20 // Reserved (deprecated, formerly ElGamal Encrypt or Sign)
|
||||
// RFC -1
|
||||
PubKeyAlgoEdDSA PublicKeyAlgorithm = 22
|
||||
)
|
||||
|
@ -507,19 +510,17 @@ func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) {
|
|||
numBytes := (int(bitLength) + 7) / 8
|
||||
mpi = make([]byte, numBytes)
|
||||
_, err = readFull(r, mpi)
|
||||
return
|
||||
}
|
||||
|
||||
// mpiLength returns the length of the given *big.Int when serialized as an
|
||||
// MPI.
|
||||
func mpiLength(n *big.Int) (mpiLengthInBytes int) {
|
||||
mpiLengthInBytes = 2 /* MPI length */
|
||||
mpiLengthInBytes += (n.BitLen() + 7) / 8
|
||||
// According to RFC 4880 3.2. we should check that the MPI has no leading
|
||||
// zeroes (at least when not an encrypted MPI?), but this implementation
|
||||
// does generate leading zeroes, so we keep accepting them.
|
||||
return
|
||||
}
|
||||
|
||||
// writeMPI serializes a big integer to w.
|
||||
func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) {
|
||||
// Note that we can produce leading zeroes, in violation of RFC 4880 3.2.
|
||||
// Implementations seem to be tolerant of them, and stripping them would
|
||||
// make it complex to guarantee matching re-serialization.
|
||||
_, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
|
||||
if err == nil {
|
||||
_, err = w.Write(mpiBytes)
|
||||
|
@ -551,6 +552,18 @@ func writeBig(w io.Writer, i *big.Int) error {
|
|||
return writeMPI(w, uint16(i.BitLen()), i.Bytes())
|
||||
}
|
||||
|
||||
// padToKeySize left-pads a MPI with zeroes to match the length of the
|
||||
// specified RSA public.
|
||||
func padToKeySize(pub *rsa.PublicKey, b []byte) []byte {
|
||||
k := (pub.N.BitLen() + 7) / 8
|
||||
if len(b) >= k {
|
||||
return b
|
||||
}
|
||||
bb := make([]byte, k)
|
||||
copy(bb[len(bb)-len(b):], b)
|
||||
return bb
|
||||
}
|
||||
|
||||
// CompressionAlgo Represents the different compression algorithms
|
||||
// supported by OpenPGP (except for BZIP2, which is not currently
|
||||
// supported). See Section 9.3 of RFC 4880.
|
||||
|
|
|
@ -44,6 +44,10 @@ type EdDSAPrivateKey struct {
|
|||
seed parsedMPI
|
||||
}
|
||||
|
||||
func (e *EdDSAPrivateKey) Seed() []byte {
|
||||
return e.seed.bytes
|
||||
}
|
||||
|
||||
func (e *EdDSAPrivateKey) Sign(digest []byte) (R, S []byte, err error) {
|
||||
r := bytes.NewReader(e.seed.bytes)
|
||||
publicKey, privateKey, err := ed25519.GenerateKey(r)
|
||||
|
@ -89,6 +93,13 @@ func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateK
|
|||
return pk
|
||||
}
|
||||
|
||||
func NewECDHPrivateKey(currentTime time.Time, priv *ecdh.PrivateKey) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
pk.PublicKey = *NewECDHPublicKey(currentTime, &priv.PublicKey)
|
||||
pk.PrivateKey = priv
|
||||
return pk
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parse(r io.Reader) (err error) {
|
||||
err = (&pk.PublicKey).parse(r)
|
||||
if err != nil {
|
||||
|
@ -415,8 +426,11 @@ func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
|
|||
return pk.parseECDHPrivateKey(data)
|
||||
case PubKeyAlgoEdDSA:
|
||||
return pk.parseEdDSAPrivateKey(data)
|
||||
case PubKeyAlgoBadElGamal:
|
||||
return errors.UnsupportedError("parsing el-gamal sign-or-encrypt privatekeys is unsupported")
|
||||
default:
|
||||
return errors.UnsupportedError("cannot parse this private key type")
|
||||
}
|
||||
panic("impossible")
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
|
||||
|
|
|
@ -27,10 +27,13 @@ import (
|
|||
"github.com/keybase/go-crypto/openpgp/ecdh"
|
||||
"github.com/keybase/go-crypto/openpgp/elgamal"
|
||||
"github.com/keybase/go-crypto/openpgp/errors"
|
||||
"github.com/keybase/go-crypto/openpgp/s2k"
|
||||
"github.com/keybase/go-crypto/rsa"
|
||||
)
|
||||
|
||||
var (
|
||||
// NIST curve P-224
|
||||
oidCurveP224 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x21}
|
||||
// NIST curve P-256
|
||||
oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}
|
||||
// NIST curve P-384
|
||||
|
@ -128,6 +131,8 @@ func (f *ecdsaKey) serialize(w io.Writer) (err error) {
|
|||
|
||||
func getCurveByOid(oid []byte) elliptic.Curve {
|
||||
switch {
|
||||
case bytes.Equal(oid, oidCurveP224):
|
||||
return elliptic.P224()
|
||||
case bytes.Equal(oid, oidCurveP256):
|
||||
return elliptic.P256()
|
||||
case bytes.Equal(oid, oidCurveP384):
|
||||
|
@ -324,6 +329,30 @@ func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *Public
|
|||
return pk
|
||||
}
|
||||
|
||||
func getCurveOid(curve elliptic.Curve) (res []byte, err error) {
|
||||
switch curve {
|
||||
case elliptic.P224():
|
||||
res = oidCurveP224
|
||||
case elliptic.P256():
|
||||
res = oidCurveP256
|
||||
case elliptic.P384():
|
||||
res = oidCurveP384
|
||||
case elliptic.P521():
|
||||
res = oidCurveP521
|
||||
case brainpool.P256r1():
|
||||
res = oidCurveP256r1
|
||||
case brainpool.P384r1():
|
||||
res = oidCurveP384r1
|
||||
case brainpool.P512r1():
|
||||
res = oidCurveP512r1
|
||||
case curve25519.Cv25519():
|
||||
res = oidCurve25519
|
||||
default:
|
||||
err = errors.UnsupportedError("unknown curve")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey {
|
||||
pk := &PublicKey{
|
||||
CreationTime: creationTime,
|
||||
|
@ -331,22 +360,34 @@ func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey
|
|||
PublicKey: pub,
|
||||
ec: new(ecdsaKey),
|
||||
}
|
||||
switch pub.Curve {
|
||||
case elliptic.P256():
|
||||
pk.ec.oid = oidCurveP256
|
||||
case elliptic.P384():
|
||||
pk.ec.oid = oidCurveP384
|
||||
case elliptic.P521():
|
||||
pk.ec.oid = oidCurveP521
|
||||
case brainpool.P256r1():
|
||||
pk.ec.oid = oidCurveP256r1
|
||||
case brainpool.P384r1():
|
||||
pk.ec.oid = oidCurveP384r1
|
||||
case brainpool.P512r1():
|
||||
pk.ec.oid = oidCurveP512r1
|
||||
oid, _ := getCurveOid(pub.Curve)
|
||||
pk.ec.oid = oid
|
||||
bs, bitLen := ecdh.Marshal(pub.Curve, pub.X, pub.Y)
|
||||
pk.ec.p.bytes = bs
|
||||
pk.ec.p.bitLength = uint16(bitLen)
|
||||
|
||||
pk.setFingerPrintAndKeyId()
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewECDHPublicKey(creationTime time.Time, pub *ecdh.PublicKey) *PublicKey {
|
||||
pk := &PublicKey{
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoECDH,
|
||||
PublicKey: pub,
|
||||
ec: new(ecdsaKey),
|
||||
}
|
||||
oid, _ := getCurveOid(pub.Curve)
|
||||
pk.ec.oid = oid
|
||||
bs, bitLen := ecdh.Marshal(pub.Curve, pub.X, pub.Y)
|
||||
pk.ec.p.bytes = bs
|
||||
pk.ec.p.bitLength = uint16(bitLen)
|
||||
|
||||
hashbyte, _ := s2k.HashToHashId(crypto.SHA512)
|
||||
pk.ecdh = &ecdhKdf{
|
||||
KdfHash: kdfHashFunction(hashbyte),
|
||||
KdfAlgo: kdfAlgorithm(CipherAES256),
|
||||
}
|
||||
pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
|
||||
pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes))
|
||||
|
||||
pk.setFingerPrintAndKeyId()
|
||||
return pk
|
||||
|
@ -377,6 +418,9 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
|
|||
return err
|
||||
}
|
||||
err = pk.edk.check()
|
||||
if err == nil {
|
||||
pk.PublicKey = ed25519.PublicKey(pk.edk.p.bytes[1:])
|
||||
}
|
||||
case PubKeyAlgoECDSA:
|
||||
pk.ec = new(ecdsaKey)
|
||||
if err = pk.ec.parse(r); err != nil {
|
||||
|
@ -393,6 +437,14 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
|
|||
return
|
||||
}
|
||||
pk.PublicKey, err = pk.ec.newECDH()
|
||||
case PubKeyAlgoBadElGamal:
|
||||
// Key has ElGamal format but nil-implementation - it will
|
||||
// load but it's not possible to do any operations using this
|
||||
// key.
|
||||
err = pk.parseElGamal(r)
|
||||
if err != nil {
|
||||
pk.PublicKey = nil
|
||||
}
|
||||
default:
|
||||
err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
|
||||
}
|
||||
|
@ -433,6 +485,8 @@ func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
|
|||
N: new(big.Int).SetBytes(pk.n.bytes),
|
||||
E: 0,
|
||||
}
|
||||
// Warning: incompatibility with crypto/rsa: keybase fork uses
|
||||
// int64 public exponents instead of int32.
|
||||
for i := 0; i < len(pk.e.bytes); i++ {
|
||||
rsa.E <<= 8
|
||||
rsa.E |= int64(pk.e.bytes[i])
|
||||
|
@ -508,7 +562,7 @@ func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) {
|
|||
pLength += 2 + uint16(len(pk.q.bytes))
|
||||
pLength += 2 + uint16(len(pk.g.bytes))
|
||||
pLength += 2 + uint16(len(pk.y.bytes))
|
||||
case PubKeyAlgoElGamal:
|
||||
case PubKeyAlgoElGamal, PubKeyAlgoBadElGamal:
|
||||
pLength += 2 + uint16(len(pk.p.bytes))
|
||||
pLength += 2 + uint16(len(pk.g.bytes))
|
||||
pLength += 2 + uint16(len(pk.y.bytes))
|
||||
|
@ -539,7 +593,7 @@ func (pk *PublicKey) Serialize(w io.Writer) (err error) {
|
|||
length += 2 + len(pk.q.bytes)
|
||||
length += 2 + len(pk.g.bytes)
|
||||
length += 2 + len(pk.y.bytes)
|
||||
case PubKeyAlgoElGamal:
|
||||
case PubKeyAlgoElGamal, PubKeyAlgoBadElGamal:
|
||||
length += 2 + len(pk.p.bytes)
|
||||
length += 2 + len(pk.g.bytes)
|
||||
length += 2 + len(pk.y.bytes)
|
||||
|
@ -587,7 +641,7 @@ func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
|
|||
return writeMPIs(w, pk.n, pk.e)
|
||||
case PubKeyAlgoDSA:
|
||||
return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
|
||||
case PubKeyAlgoElGamal:
|
||||
case PubKeyAlgoElGamal, PubKeyAlgoBadElGamal:
|
||||
return writeMPIs(w, pk.p, pk.g, pk.y)
|
||||
case PubKeyAlgoECDSA:
|
||||
return pk.ec.serialize(w)
|
||||
|
@ -637,7 +691,7 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
|
|||
switch pk.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
||||
rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
|
||||
err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
|
||||
err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes))
|
||||
if err != nil {
|
||||
return errors.SignatureError("RSA verification failure")
|
||||
}
|
||||
|
@ -694,7 +748,7 @@ func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err
|
|||
switch pk.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
||||
rsaPublicKey := pk.PublicKey.(*rsa.PublicKey)
|
||||
if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
|
||||
if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)); err != nil {
|
||||
return errors.SignatureError("RSA verification failure")
|
||||
}
|
||||
return
|
||||
|
@ -910,7 +964,7 @@ func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
|
|||
bitLength = pk.n.bitLength
|
||||
case PubKeyAlgoDSA:
|
||||
bitLength = pk.p.bitLength
|
||||
case PubKeyAlgoElGamal:
|
||||
case PubKeyAlgoElGamal, PubKeyAlgoBadElGamal:
|
||||
bitLength = pk.p.bitLength
|
||||
case PubKeyAlgoECDH:
|
||||
ecdhPublicKey := pk.PublicKey.(*ecdh.PublicKey)
|
||||
|
@ -928,3 +982,12 @@ func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (pk *PublicKey) ErrorIfDeprecated() error {
|
||||
switch pk.PubKeyAlgo {
|
||||
case PubKeyAlgoBadElGamal:
|
||||
return errors.DeprecatedKeyError("ElGamal Encrypt or Sign (algo 20) is deprecated")
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,6 +105,8 @@ func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) {
|
|||
return
|
||||
}
|
||||
rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)}
|
||||
// Warning: incompatibility with crypto/rsa: keybase fork uses
|
||||
// int64 public exponents instead of int32.
|
||||
for i := 0; i < len(pk.e.bytes); i++ {
|
||||
rsa.E <<= 8
|
||||
rsa.E |= int64(pk.e.bytes[i])
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"strconv"
|
||||
|
@ -384,6 +385,7 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
|||
err = errors.StructuralError("empty key flags subpacket")
|
||||
return
|
||||
}
|
||||
if subpacket[0] != 0 {
|
||||
sig.FlagsValid = true
|
||||
if subpacket[0]&KeyFlagCertify != 0 {
|
||||
sig.FlagCertify = true
|
||||
|
@ -397,6 +399,7 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
|||
if subpacket[0]&KeyFlagEncryptStorage != 0 {
|
||||
sig.FlagEncryptStorage = true
|
||||
}
|
||||
}
|
||||
case reasonForRevocationSubpacket:
|
||||
// Reason For Revocation, section 5.2.3.23
|
||||
if !isHashed {
|
||||
|
@ -624,6 +627,13 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
|
|||
return
|
||||
}
|
||||
|
||||
// Parameter check, if this is wrong we will make a signature but
|
||||
// not serialize it later.
|
||||
if sig.PubKeyAlgo != priv.PubKeyAlgo {
|
||||
err = errors.InvalidArgumentError("signature pub key algo does not match priv key")
|
||||
return
|
||||
}
|
||||
|
||||
switch priv.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
||||
sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
|
||||
|
@ -637,26 +647,29 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
|
|||
digest = digest[:subgroupSize]
|
||||
}
|
||||
r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
|
||||
if err == nil {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sig.DSASigR.bytes = r.Bytes()
|
||||
sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
|
||||
sig.DSASigS.bytes = s.Bytes()
|
||||
sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
|
||||
}
|
||||
case PubKeyAlgoECDSA:
|
||||
r, s, err := ecdsa.Sign(config.Random(), priv.PrivateKey.(*ecdsa.PrivateKey), digest)
|
||||
if err == nil {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sig.ECDSASigR = FromBig(r)
|
||||
sig.ECDSASigS = FromBig(s)
|
||||
}
|
||||
case PubKeyAlgoEdDSA:
|
||||
r, s, err := priv.PrivateKey.(*EdDSAPrivateKey).Sign(digest)
|
||||
if err == nil {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sig.EdDSASigR = FromBytes(r)
|
||||
sig.EdDSASigS = FromBytes(s)
|
||||
}
|
||||
default:
|
||||
err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
|
||||
err = errors.UnsupportedError("public key algorithm for signing: " + strconv.Itoa(int(priv.PubKeyAlgo)))
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -704,6 +717,28 @@ func (sig *Signature) SignKeyWithSigner(signeePubKey *PublicKey, signerPubKey *P
|
|||
return sig.Sign(s, nil, config)
|
||||
}
|
||||
|
||||
// CrossSignKey creates PrimaryKeyBinding signature in sig.EmbeddedSignature by
|
||||
// signing `primary` key's hash using `priv` subkey private key. Primary public
|
||||
// key is the `signee` here.
|
||||
func (sig *Signature) CrossSignKey(primary *PublicKey, priv *PrivateKey, config *Config) error {
|
||||
if len(sig.outSubpackets) > 0 {
|
||||
return fmt.Errorf("outSubpackets already exists, looks like CrossSignKey was called after Sign")
|
||||
}
|
||||
|
||||
sig.EmbeddedSignature = &Signature{
|
||||
CreationTime: sig.CreationTime,
|
||||
SigType: SigTypePrimaryKeyBinding,
|
||||
PubKeyAlgo: priv.PubKeyAlgo,
|
||||
Hash: sig.Hash,
|
||||
}
|
||||
|
||||
h, err := keySignatureHash(primary, &priv.PublicKey, sig.Hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return sig.EmbeddedSignature.Sign(h, priv, config)
|
||||
}
|
||||
|
||||
// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
|
||||
// called first.
|
||||
func (sig *Signature) Serialize(w io.Writer) (err error) {
|
||||
|
@ -832,6 +867,14 @@ func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
|
|||
subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
|
||||
}
|
||||
|
||||
if sig.EmbeddedSignature != nil {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if err := sig.EmbeddedSignature.Serialize(buf); err == nil {
|
||||
byteContent := buf.Bytes()[2:] // skip 2-byte length header
|
||||
subpackets = append(subpackets, outputSubpacket{false, embeddedSignatureSubpacket, true, byteContent})
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -91,10 +91,10 @@ func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunc
|
|||
return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
|
||||
}
|
||||
plaintextKey = plaintextKey[1:]
|
||||
if l := len(plaintextKey); l == 0 || l%cipherFunc.blockSize() != 0 {
|
||||
return nil, cipherFunc, errors.StructuralError("length of decrypted key not a multiple of block size")
|
||||
if l, cipherKeySize := len(plaintextKey), cipherFunc.KeySize(); l != cipherFunc.KeySize() {
|
||||
return nil, cipherFunc, errors.StructuralError("length of decrypted key (" + strconv.Itoa(l) + ") " +
|
||||
"not equal to cipher keysize (" + strconv.Itoa(cipherKeySize) + ")")
|
||||
}
|
||||
|
||||
return plaintextKey, cipherFunc, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,9 @@ type MessageDetails struct {
|
|||
Signature *packet.Signature // the signature packet itself, if v4 (default)
|
||||
SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature
|
||||
|
||||
// Does the Message include multiple signatures? Also called "nested signatures".
|
||||
MultiSig bool
|
||||
|
||||
decrypted io.ReadCloser
|
||||
}
|
||||
|
||||
|
@ -158,8 +161,15 @@ FindKey:
|
|||
continue
|
||||
}
|
||||
if !pk.key.PrivateKey.Encrypted {
|
||||
if pk.key.PrivateKey.PrivateKey == nil {
|
||||
// Key is stubbed
|
||||
continue
|
||||
}
|
||||
if len(pk.encryptedKey.Key) == 0 {
|
||||
pk.encryptedKey.Decrypt(pk.key.PrivateKey, config)
|
||||
err := pk.encryptedKey.Decrypt(pk.key.PrivateKey, config)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if len(pk.encryptedKey.Key) == 0 {
|
||||
continue
|
||||
|
@ -244,8 +254,17 @@ FindLiteralData:
|
|||
return nil, err
|
||||
}
|
||||
case *packet.OnePassSignature:
|
||||
if !p.IsLast {
|
||||
return nil, errors.UnsupportedError("nested signatures")
|
||||
if md.IsSigned {
|
||||
// If IsSigned is set, it means we have multiple
|
||||
// OnePassSignature packets.
|
||||
md.MultiSig = true
|
||||
if md.SignedBy != nil {
|
||||
// We've already found the signature we were looking
|
||||
// for, made by key that we had in keyring and can
|
||||
// check signature against. Continue with that instead
|
||||
// of trying to find another.
|
||||
continue FindLiteralData
|
||||
}
|
||||
}
|
||||
|
||||
h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
|
||||
|
@ -329,17 +348,36 @@ func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
|
|||
n, err = scr.md.LiteralData.Body.Read(buf)
|
||||
scr.wrappedHash.Write(buf[:n])
|
||||
if err == io.EOF {
|
||||
for {
|
||||
var p packet.Packet
|
||||
p, scr.md.SignatureError = scr.packets.Next()
|
||||
if scr.md.SignatureError != nil {
|
||||
if scr.md.MultiSig {
|
||||
// If we are in MultiSig, we might have found other
|
||||
// signature that cannot be verified using our key.
|
||||
// Clear Signature field so it's clear for consumers
|
||||
// that this message failed to verify.
|
||||
scr.md.Signature = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var ok bool
|
||||
if scr.md.Signature, ok = p.(*packet.Signature); ok {
|
||||
var err error
|
||||
if keyID := scr.md.Signature.IssuerKeyId; keyID != nil {
|
||||
if *keyID != scr.md.SignedBy.PublicKey.KeyId {
|
||||
if scr.md.MultiSig {
|
||||
continue // try again to find a sig we can verify
|
||||
}
|
||||
err = errors.StructuralError("bad key id")
|
||||
}
|
||||
}
|
||||
if fingerprint := scr.md.Signature.IssuerFingerprint; fingerprint != nil {
|
||||
if !hmac.Equal(fingerprint, scr.md.SignedBy.PublicKey.Fingerprint[:]) {
|
||||
if scr.md.MultiSig {
|
||||
continue // try again to find a sig we can verify
|
||||
}
|
||||
err = errors.StructuralError("bad key fingerprint")
|
||||
}
|
||||
}
|
||||
|
@ -354,6 +392,12 @@ func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// Parse only one packet by default, unless message is MultiSig. Then
|
||||
// we ask for more packets after discovering non-matching signature,
|
||||
// until we find one that we can verify.
|
||||
break
|
||||
}
|
||||
|
||||
// The SymmetricallyEncrypted packet, if any, might have an
|
||||
// unsigned hash of its own. In order to check this we need to
|
||||
// close that Reader.
|
||||
|
|
|
@ -458,7 +458,18 @@ func AttachedSign(out io.WriteCloser, signed Entity, hints *FileHints,
|
|||
return
|
||||
}
|
||||
|
||||
hasher := crypto.SHA512
|
||||
if algo := config.Compression(); algo != packet.CompressionNone {
|
||||
var compConfig *packet.CompressionConfig
|
||||
if config != nil {
|
||||
compConfig = config.CompressionConfig
|
||||
}
|
||||
out, err = packet.SerializeCompressed(out, algo, compConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
hasher := config.Hash() // defaults to SHA-256
|
||||
|
||||
ops := &packet.OnePassSignature{
|
||||
SigType: packet.SigTypeBinary,
|
||||
|
|
|
@ -253,7 +253,7 @@ github.com/jessevdk/go-flags
|
|||
github.com/kballard/go-shellquote
|
||||
# github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd
|
||||
github.com/kevinburke/ssh_config
|
||||
# github.com/keybase/go-crypto v0.0.0-20170605145657-00ac4db533f6
|
||||
# github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
|
||||
github.com/keybase/go-crypto/brainpool
|
||||
github.com/keybase/go-crypto/cast5
|
||||
github.com/keybase/go-crypto/curve25519
|
||||
|
|
Loading…
Reference in New Issue