mirror of https://github.com/dexidp/dex.git
18 changed files with 4585 additions and 169 deletions
@ -0,0 +1,181 @@
|
||||
// Copyright 2016 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 ed25519 implements the Ed25519 signature algorithm. See
|
||||
// http://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.
|
||||
package ed25519 |
||||
|
||||
// This code is a port of the public domain, “ref10” implementation of ed25519
|
||||
// from SUPERCOP.
|
||||
|
||||
import ( |
||||
"crypto" |
||||
cryptorand "crypto/rand" |
||||
"crypto/sha512" |
||||
"crypto/subtle" |
||||
"errors" |
||||
"io" |
||||
"strconv" |
||||
|
||||
"golang.org/x/crypto/ed25519/internal/edwards25519" |
||||
) |
||||
|
||||
const ( |
||||
// PublicKeySize is the size, in bytes, of public keys as used in this package.
|
||||
PublicKeySize = 32 |
||||
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
|
||||
PrivateKeySize = 64 |
||||
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
|
||||
SignatureSize = 64 |
||||
) |
||||
|
||||
// PublicKey is the type of Ed25519 public keys.
|
||||
type PublicKey []byte |
||||
|
||||
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
|
||||
type PrivateKey []byte |
||||
|
||||
// Public returns the PublicKey corresponding to priv.
|
||||
func (priv PrivateKey) Public() crypto.PublicKey { |
||||
publicKey := make([]byte, PublicKeySize) |
||||
copy(publicKey, priv[32:]) |
||||
return PublicKey(publicKey) |
||||
} |
||||
|
||||
// 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
|
||||
// indicate the message hasn't been hashed. This can be achieved by passing
|
||||
// crypto.Hash(0) as the value for opts.
|
||||
func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { |
||||
if opts.HashFunc() != crypto.Hash(0) { |
||||
return nil, errors.New("ed25519: cannot sign hashed message") |
||||
} |
||||
|
||||
return Sign(priv, message), nil |
||||
} |
||||
|
||||
// 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) { |
||||
if rand == nil { |
||||
rand = cryptorand.Reader |
||||
} |
||||
|
||||
privateKey = make([]byte, PrivateKeySize) |
||||
publicKey = make([]byte, PublicKeySize) |
||||
_, err = io.ReadFull(rand, privateKey[:32]) |
||||
if err != nil { |
||||
return nil, nil, err |
||||
} |
||||
|
||||
digest := sha512.Sum512(privateKey[:32]) |
||||
digest[0] &= 248 |
||||
digest[31] &= 127 |
||||
digest[31] |= 64 |
||||
|
||||
var A edwards25519.ExtendedGroupElement |
||||
var hBytes [32]byte |
||||
copy(hBytes[:], digest[:]) |
||||
edwards25519.GeScalarMultBase(&A, &hBytes) |
||||
var publicKeyBytes [32]byte |
||||
A.ToBytes(&publicKeyBytes) |
||||
|
||||
copy(privateKey[32:], publicKeyBytes[:]) |
||||
copy(publicKey, publicKeyBytes[:]) |
||||
|
||||
return publicKey, privateKey, nil |
||||
} |
||||
|
||||
// Sign signs the message with privateKey and returns a signature. It will
|
||||
// panic if len(privateKey) is not PrivateKeySize.
|
||||
func Sign(privateKey PrivateKey, message []byte) []byte { |
||||
if l := len(privateKey); l != PrivateKeySize { |
||||
panic("ed25519: bad private key length: " + strconv.Itoa(l)) |
||||
} |
||||
|
||||
h := sha512.New() |
||||
h.Write(privateKey[:32]) |
||||
|
||||
var digest1, messageDigest, hramDigest [64]byte |
||||
var expandedSecretKey [32]byte |
||||
h.Sum(digest1[:0]) |
||||
copy(expandedSecretKey[:], digest1[:]) |
||||
expandedSecretKey[0] &= 248 |
||||
expandedSecretKey[31] &= 63 |
||||
expandedSecretKey[31] |= 64 |
||||
|
||||
h.Reset() |
||||
h.Write(digest1[32:]) |
||||
h.Write(message) |
||||
h.Sum(messageDigest[:0]) |
||||
|
||||
var messageDigestReduced [32]byte |
||||
edwards25519.ScReduce(&messageDigestReduced, &messageDigest) |
||||
var R edwards25519.ExtendedGroupElement |
||||
edwards25519.GeScalarMultBase(&R, &messageDigestReduced) |
||||
|
||||
var encodedR [32]byte |
||||
R.ToBytes(&encodedR) |
||||
|
||||
h.Reset() |
||||
h.Write(encodedR[:]) |
||||
h.Write(privateKey[32:]) |
||||
h.Write(message) |
||||
h.Sum(hramDigest[:0]) |
||||
var hramDigestReduced [32]byte |
||||
edwards25519.ScReduce(&hramDigestReduced, &hramDigest) |
||||
|
||||
var s [32]byte |
||||
edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced) |
||||
|
||||
signature := make([]byte, SignatureSize) |
||||
copy(signature[:], encodedR[:]) |
||||
copy(signature[32:], s[:]) |
||||
|
||||
return signature |
||||
} |
||||
|
||||
// Verify reports whether sig is a valid signature of message by publicKey. It
|
||||
// will panic if len(publicKey) is not PublicKeySize.
|
||||
func Verify(publicKey PublicKey, message, sig []byte) bool { |
||||
if l := len(publicKey); l != PublicKeySize { |
||||
panic("ed25519: bad public key length: " + strconv.Itoa(l)) |
||||
} |
||||
|
||||
if len(sig) != SignatureSize || sig[63]&224 != 0 { |
||||
return false |
||||
} |
||||
|
||||
var A edwards25519.ExtendedGroupElement |
||||
var publicKeyBytes [32]byte |
||||
copy(publicKeyBytes[:], publicKey) |
||||
if !A.FromBytes(&publicKeyBytes) { |
||||
return false |
||||
} |
||||
edwards25519.FeNeg(&A.X, &A.X) |
||||
edwards25519.FeNeg(&A.T, &A.T) |
||||
|
||||
h := sha512.New() |
||||
h.Write(sig[:32]) |
||||
h.Write(publicKey[:]) |
||||
h.Write(message) |
||||
var digest [64]byte |
||||
h.Sum(digest[:0]) |
||||
|
||||
var hReduced [32]byte |
||||
edwards25519.ScReduce(&hReduced, &digest) |
||||
|
||||
var R edwards25519.ProjectiveGroupElement |
||||
var b [32]byte |
||||
copy(b[:], sig[32:]) |
||||
edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b) |
||||
|
||||
var checkR [32]byte |
||||
R.ToBytes(&checkR) |
||||
return subtle.ConstantTimeCompare(sig[:32], checkR[:]) == 1 |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,77 @@
|
||||
// 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.
|
||||
|
||||
/* |
||||
Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC |
||||
2898 / PKCS #5 v2.0. |
||||
|
||||
A key derivation function is useful when encrypting data based on a password |
||||
or any other not-fully-random data. It uses a pseudorandom function to derive |
||||
a secure encryption key based on the password. |
||||
|
||||
While v2.0 of the standard defines only one pseudorandom function to use, |
||||
HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved |
||||
Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To |
||||
choose, you can pass the `New` functions from the different SHA packages to |
||||
pbkdf2.Key. |
||||
*/ |
||||
package pbkdf2 // import "golang.org/x/crypto/pbkdf2"
|
||||
|
||||
import ( |
||||
"crypto/hmac" |
||||
"hash" |
||||
) |
||||
|
||||
// Key derives a key from the password, salt and iteration count, returning a
|
||||
// []byte of length keylen that can be used as cryptographic key. The key is
|
||||
// derived based on the method described as PBKDF2 with the HMAC variant using
|
||||
// the supplied hash function.
|
||||
//
|
||||
// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
|
||||
// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
|
||||
// doing:
|
||||
//
|
||||
// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New)
|
||||
//
|
||||
// Remember to get a good random salt. At least 8 bytes is recommended by the
|
||||
// RFC.
|
||||
//
|
||||
// Using a higher iteration count will increase the cost of an exhaustive
|
||||
// search but will also make derivation proportionally slower.
|
||||
func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { |
||||
prf := hmac.New(h, password) |
||||
hashLen := prf.Size() |
||||
numBlocks := (keyLen + hashLen - 1) / hashLen |
||||
|
||||
var buf [4]byte |
||||
dk := make([]byte, 0, numBlocks*hashLen) |
||||
U := make([]byte, hashLen) |
||||
for block := 1; block <= numBlocks; block++ { |
||||
// N.B.: || means concatenation, ^ means XOR
|
||||
// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
|
||||
// U_1 = PRF(password, salt || uint(i))
|
||||
prf.Reset() |
||||
prf.Write(salt) |
||||
buf[0] = byte(block >> 24) |
||||
buf[1] = byte(block >> 16) |
||||
buf[2] = byte(block >> 8) |
||||
buf[3] = byte(block) |
||||
prf.Write(buf[:4]) |
||||
dk = prf.Sum(dk) |
||||
T := dk[len(dk)-hashLen:] |
||||
copy(U, T) |
||||
|
||||
// U_n = PRF(password, U_(n-1))
|
||||
for n := 2; n <= iter; n++ { |
||||
prf.Reset() |
||||
prf.Write(U) |
||||
U = U[:0] |
||||
U = prf.Sum(U) |
||||
for x := range U { |
||||
T[x] ^= U[x] |
||||
} |
||||
} |
||||
} |
||||
return dk[:keyLen] |
||||
} |
||||
@ -0,0 +1,83 @@
|
||||
/*- |
||||
* Copyright 2018 Square Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package jose |
||||
|
||||
// OpaqueSigner is an interface that supports signing payloads with opaque
|
||||
// private key(s). Private key operations preformed by implementors may, for
|
||||
// example, occur in a hardware module. An OpaqueSigner may rotate signing keys
|
||||
// transparently to the user of this interface.
|
||||
type OpaqueSigner interface { |
||||
// Public returns the public key of the current signing key.
|
||||
Public() *JSONWebKey |
||||
// Algs returns a list of supported signing algorithms.
|
||||
Algs() []SignatureAlgorithm |
||||
// SignPayload signs a payload with the current signing key using the given
|
||||
// algorithm.
|
||||
SignPayload(payload []byte, alg SignatureAlgorithm) ([]byte, error) |
||||
} |
||||
|
||||
type opaqueSigner struct { |
||||
signer OpaqueSigner |
||||
} |
||||
|
||||
func newOpaqueSigner(alg SignatureAlgorithm, signer OpaqueSigner) (recipientSigInfo, error) { |
||||
var algSupported bool |
||||
for _, salg := range signer.Algs() { |
||||
if alg == salg { |
||||
algSupported = true |
||||
break |
||||
} |
||||
} |
||||
if !algSupported { |
||||
return recipientSigInfo{}, ErrUnsupportedAlgorithm |
||||
} |
||||
|
||||
return recipientSigInfo{ |
||||
sigAlg: alg, |
||||
publicKey: signer.Public, |
||||
signer: &opaqueSigner{ |
||||
signer: signer, |
||||
}, |
||||
}, nil |
||||
} |
||||
|
||||
func (o *opaqueSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { |
||||
out, err := o.signer.SignPayload(payload, alg) |
||||
if err != nil { |
||||
return Signature{}, err |
||||
} |
||||
|
||||
return Signature{ |
||||
Signature: out, |
||||
protected: &rawHeader{}, |
||||
}, nil |
||||
} |
||||
|
||||
// OpaqueVerifier is an interface that supports verifying payloads with opaque
|
||||
// public key(s). An OpaqueSigner may rotate signing keys transparently to the
|
||||
// user of this interface.
|
||||
type OpaqueVerifier interface { |
||||
VerifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error |
||||
} |
||||
|
||||
type opaqueVerifier struct { |
||||
verifier OpaqueVerifier |
||||
} |
||||
|
||||
func (o *opaqueVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error { |
||||
return o.verifier.VerifyPayload(payload, signature, alg) |
||||
} |
||||
Loading…
Reference in new issue