forked from forgejo/forgejo
Switch to keybase go-crypto (for some elliptic curve key) + test (#1925)
* Switch to keybase go-crypto (for some elliptic curve key) + test
* Use assert.NoError
and add a little more context to failing test description
* Use assert.(No)Error everywhere 🌈
and assert.Error in place of .Nil/.NotNil
This commit is contained in:
parent
5e92b82ac6
commit
274149dd14
56 changed files with 10621 additions and 925 deletions
297
vendor/github.com/keybase/go-crypto/rsa/pss.go
generated
vendored
Normal file
297
vendor/github.com/keybase/go-crypto/rsa/pss.go
generated
vendored
Normal file
|
@ -0,0 +1,297 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rsa
|
||||
|
||||
// This file implements the PSS signature scheme [1].
|
||||
//
|
||||
// [1] http://www.rsa.com/rsalabs/pkcs/files/h11300-wp-pkcs-1v2-2-rsa-cryptography-standard.pdf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"errors"
|
||||
"hash"
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) {
|
||||
// See [1], section 9.1.1
|
||||
hLen := hash.Size()
|
||||
sLen := len(salt)
|
||||
emLen := (emBits + 7) / 8
|
||||
|
||||
// 1. If the length of M is greater than the input limitation for the
|
||||
// hash function (2^61 - 1 octets for SHA-1), output "message too
|
||||
// long" and stop.
|
||||
//
|
||||
// 2. Let mHash = Hash(M), an octet string of length hLen.
|
||||
|
||||
if len(mHash) != hLen {
|
||||
return nil, errors.New("crypto/rsa: input must be hashed message")
|
||||
}
|
||||
|
||||
// 3. If emLen < hLen + sLen + 2, output "encoding error" and stop.
|
||||
|
||||
if emLen < hLen+sLen+2 {
|
||||
return nil, errors.New("crypto/rsa: encoding error")
|
||||
}
|
||||
|
||||
em := make([]byte, emLen)
|
||||
db := em[:emLen-sLen-hLen-2+1+sLen]
|
||||
h := em[emLen-sLen-hLen-2+1+sLen : emLen-1]
|
||||
|
||||
// 4. Generate a random octet string salt of length sLen; if sLen = 0,
|
||||
// then salt is the empty string.
|
||||
//
|
||||
// 5. Let
|
||||
// M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt;
|
||||
//
|
||||
// M' is an octet string of length 8 + hLen + sLen with eight
|
||||
// initial zero octets.
|
||||
//
|
||||
// 6. Let H = Hash(M'), an octet string of length hLen.
|
||||
|
||||
var prefix [8]byte
|
||||
|
||||
hash.Write(prefix[:])
|
||||
hash.Write(mHash)
|
||||
hash.Write(salt)
|
||||
|
||||
h = hash.Sum(h[:0])
|
||||
hash.Reset()
|
||||
|
||||
// 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2
|
||||
// zero octets. The length of PS may be 0.
|
||||
//
|
||||
// 8. Let DB = PS || 0x01 || salt; DB is an octet string of length
|
||||
// emLen - hLen - 1.
|
||||
|
||||
db[emLen-sLen-hLen-2] = 0x01
|
||||
copy(db[emLen-sLen-hLen-1:], salt)
|
||||
|
||||
// 9. Let dbMask = MGF(H, emLen - hLen - 1).
|
||||
//
|
||||
// 10. Let maskedDB = DB \xor dbMask.
|
||||
|
||||
mgf1XOR(db, hash, h)
|
||||
|
||||
// 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in
|
||||
// maskedDB to zero.
|
||||
|
||||
db[0] &= (0xFF >> uint(8*emLen-emBits))
|
||||
|
||||
// 12. Let EM = maskedDB || H || 0xbc.
|
||||
em[emLen-1] = 0xBC
|
||||
|
||||
// 13. Output EM.
|
||||
return em, nil
|
||||
}
|
||||
|
||||
func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
|
||||
// 1. If the length of M is greater than the input limitation for the
|
||||
// hash function (2^61 - 1 octets for SHA-1), output "inconsistent"
|
||||
// and stop.
|
||||
//
|
||||
// 2. Let mHash = Hash(M), an octet string of length hLen.
|
||||
hLen := hash.Size()
|
||||
if hLen != len(mHash) {
|
||||
return ErrVerification
|
||||
}
|
||||
|
||||
// 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop.
|
||||
emLen := (emBits + 7) / 8
|
||||
if emLen < hLen+sLen+2 {
|
||||
return ErrVerification
|
||||
}
|
||||
|
||||
// 4. If the rightmost octet of EM does not have hexadecimal value
|
||||
// 0xbc, output "inconsistent" and stop.
|
||||
if em[len(em)-1] != 0xBC {
|
||||
return ErrVerification
|
||||
}
|
||||
|
||||
// 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and
|
||||
// let H be the next hLen octets.
|
||||
db := em[:emLen-hLen-1]
|
||||
h := em[emLen-hLen-1 : len(em)-1]
|
||||
|
||||
// 6. If the leftmost 8 * emLen - emBits bits of the leftmost octet in
|
||||
// maskedDB are not all equal to zero, output "inconsistent" and
|
||||
// stop.
|
||||
if em[0]&(0xFF<<uint(8-(8*emLen-emBits))) != 0 {
|
||||
return ErrVerification
|
||||
}
|
||||
|
||||
// 7. Let dbMask = MGF(H, emLen - hLen - 1).
|
||||
//
|
||||
// 8. Let DB = maskedDB \xor dbMask.
|
||||
mgf1XOR(db, hash, h)
|
||||
|
||||
// 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB
|
||||
// to zero.
|
||||
db[0] &= (0xFF >> uint(8*emLen-emBits))
|
||||
|
||||
if sLen == PSSSaltLengthAuto {
|
||||
FindSaltLength:
|
||||
for sLen = emLen - (hLen + 2); sLen >= 0; sLen-- {
|
||||
switch db[emLen-hLen-sLen-2] {
|
||||
case 1:
|
||||
break FindSaltLength
|
||||
case 0:
|
||||
continue
|
||||
default:
|
||||
return ErrVerification
|
||||
}
|
||||
}
|
||||
if sLen < 0 {
|
||||
return ErrVerification
|
||||
}
|
||||
} else {
|
||||
// 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
|
||||
// or if the octet at position emLen - hLen - sLen - 1 (the leftmost
|
||||
// position is "position 1") does not have hexadecimal value 0x01,
|
||||
// output "inconsistent" and stop.
|
||||
for _, e := range db[:emLen-hLen-sLen-2] {
|
||||
if e != 0x00 {
|
||||
return ErrVerification
|
||||
}
|
||||
}
|
||||
if db[emLen-hLen-sLen-2] != 0x01 {
|
||||
return ErrVerification
|
||||
}
|
||||
}
|
||||
|
||||
// 11. Let salt be the last sLen octets of DB.
|
||||
salt := db[len(db)-sLen:]
|
||||
|
||||
// 12. Let
|
||||
// M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ;
|
||||
// M' is an octet string of length 8 + hLen + sLen with eight
|
||||
// initial zero octets.
|
||||
//
|
||||
// 13. Let H' = Hash(M'), an octet string of length hLen.
|
||||
var prefix [8]byte
|
||||
hash.Write(prefix[:])
|
||||
hash.Write(mHash)
|
||||
hash.Write(salt)
|
||||
|
||||
h0 := hash.Sum(nil)
|
||||
|
||||
// 14. If H = H', output "consistent." Otherwise, output "inconsistent."
|
||||
if !bytes.Equal(h0, h) {
|
||||
return ErrVerification
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// signPSSWithSalt calculates the signature of hashed using PSS [1] with specified salt.
|
||||
// Note that hashed must be the result of hashing the input message using the
|
||||
// given hash function. salt is a random sequence of bytes whose length will be
|
||||
// later used to verify the signature.
|
||||
func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) {
|
||||
nBits := priv.N.BitLen()
|
||||
em, err := emsaPSSEncode(hashed, nBits-1, salt, hash.New())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
m := new(big.Int).SetBytes(em)
|
||||
c, err := decryptAndCheck(rand, priv, m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s = make([]byte, (nBits+7)/8)
|
||||
copyWithLeftPad(s, c.Bytes())
|
||||
return
|
||||
}
|
||||
|
||||
const (
|
||||
// PSSSaltLengthAuto causes the salt in a PSS signature to be as large
|
||||
// as possible when signing, and to be auto-detected when verifying.
|
||||
PSSSaltLengthAuto = 0
|
||||
// PSSSaltLengthEqualsHash causes the salt length to equal the length
|
||||
// of the hash used in the signature.
|
||||
PSSSaltLengthEqualsHash = -1
|
||||
)
|
||||
|
||||
// PSSOptions contains options for creating and verifying PSS signatures.
|
||||
type PSSOptions struct {
|
||||
// SaltLength controls the length of the salt used in the PSS
|
||||
// signature. It can either be a number of bytes, or one of the special
|
||||
// PSSSaltLength constants.
|
||||
SaltLength int
|
||||
|
||||
// Hash, if not zero, overrides the hash function passed to SignPSS.
|
||||
// This is the only way to specify the hash function when using the
|
||||
// crypto.Signer interface.
|
||||
Hash crypto.Hash
|
||||
}
|
||||
|
||||
// HashFunc returns pssOpts.Hash so that PSSOptions implements
|
||||
// crypto.SignerOpts.
|
||||
func (pssOpts *PSSOptions) HashFunc() crypto.Hash {
|
||||
return pssOpts.Hash
|
||||
}
|
||||
|
||||
func (opts *PSSOptions) saltLength() int {
|
||||
if opts == nil {
|
||||
return PSSSaltLengthAuto
|
||||
}
|
||||
return opts.SaltLength
|
||||
}
|
||||
|
||||
// SignPSS calculates the signature of hashed using RSASSA-PSS [1].
|
||||
// Note that hashed must be the result of hashing the input message using the
|
||||
// given hash function. The opts argument may be nil, in which case sensible
|
||||
// defaults are used.
|
||||
func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) (s []byte, err error) {
|
||||
saltLength := opts.saltLength()
|
||||
switch saltLength {
|
||||
case PSSSaltLengthAuto:
|
||||
saltLength = (priv.N.BitLen()+7)/8 - 2 - hash.Size()
|
||||
case PSSSaltLengthEqualsHash:
|
||||
saltLength = hash.Size()
|
||||
}
|
||||
|
||||
if opts != nil && opts.Hash != 0 {
|
||||
hash = opts.Hash
|
||||
}
|
||||
|
||||
salt := make([]byte, saltLength)
|
||||
if _, err = io.ReadFull(rand, salt); err != nil {
|
||||
return
|
||||
}
|
||||
return signPSSWithSalt(rand, priv, hash, hashed, salt)
|
||||
}
|
||||
|
||||
// VerifyPSS verifies a PSS signature.
|
||||
// hashed is the result of hashing the input message using the given hash
|
||||
// function and sig is the signature. A valid signature is indicated by
|
||||
// returning a nil error. The opts argument may be nil, in which case sensible
|
||||
// defaults are used.
|
||||
func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, opts *PSSOptions) error {
|
||||
return verifyPSS(pub, hash, hashed, sig, opts.saltLength())
|
||||
}
|
||||
|
||||
// verifyPSS verifies a PSS signature with the given salt length.
|
||||
func verifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, saltLen int) error {
|
||||
nBits := pub.N.BitLen()
|
||||
if len(sig) != (nBits+7)/8 {
|
||||
return ErrVerification
|
||||
}
|
||||
s := new(big.Int).SetBytes(sig)
|
||||
m := encrypt(new(big.Int), pub, s)
|
||||
emBits := nBits - 1
|
||||
emLen := (emBits + 7) / 8
|
||||
if emLen < len(m.Bytes()) {
|
||||
return ErrVerification
|
||||
}
|
||||
em := make([]byte, emLen)
|
||||
copyWithLeftPad(em, m.Bytes())
|
||||
if saltLen == PSSSaltLengthEqualsHash {
|
||||
saltLen = hash.Size()
|
||||
}
|
||||
return emsaPSSVerify(hashed, em, emBits, saltLen, hash.New())
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue