forked from golang-jwt/jwt
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds simple reimplementation of fillBytesInt for go 1.14 support Fix golang-jwt#50 Signed-off-by: Andrew Thornton <art27@cantab.net>
- Loading branch information
Showing
3 changed files
with
131 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
//+build !go1.15 | ||
|
||
package jwt | ||
|
||
import ( | ||
"crypto/ecdsa" | ||
"crypto/rand" | ||
"math/big" | ||
"math/bits" | ||
) | ||
|
||
// Implements the Sign method from SigningMethod | ||
// For this signing method, key must be an ecdsa.PrivateKey struct | ||
func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) { | ||
// Get the key | ||
var ecdsaKey *ecdsa.PrivateKey | ||
switch k := key.(type) { | ||
case *ecdsa.PrivateKey: | ||
ecdsaKey = k | ||
default: | ||
return "", ErrInvalidKeyType | ||
} | ||
|
||
// Create the hasher | ||
if !m.Hash.Available() { | ||
return "", ErrHashUnavailable | ||
} | ||
|
||
hasher := m.Hash.New() | ||
hasher.Write([]byte(signingString)) | ||
|
||
// Sign the string and return r, s | ||
if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil { | ||
curveBits := ecdsaKey.Curve.Params().BitSize | ||
|
||
if m.CurveBits != curveBits { | ||
return "", ErrInvalidKey | ||
} | ||
|
||
keyBytes := curveBits / 8 | ||
if curveBits%8 > 0 { | ||
keyBytes += 1 | ||
} | ||
|
||
// We serialize the outputs (r and s) into big-endian byte arrays | ||
// padded with zeros on the left to make sure the sizes work out. | ||
// Output must be 2*keyBytes long. | ||
out := make([]byte, 2*keyBytes) | ||
fillBytesInt(r, out[0:keyBytes]) // r is assigned to the first half of output. | ||
fillBytesInt(s, out[keyBytes:]) // s is assigned to the second half of output. | ||
|
||
return EncodeSegment(out), nil | ||
} else { | ||
return "", err | ||
} | ||
} | ||
|
||
func fillBytesInt(x *big.Int, buf []byte) []byte { | ||
// Clear whole buffer. (This gets optimized into a memclr.) | ||
for i := range buf { | ||
buf[i] = 0 | ||
} | ||
i := len(buf) | ||
for _, d := range x.Bits() { | ||
for j := 0; j < (bits.UintSize / 8); j++ { | ||
i-- | ||
if i >= 0 { | ||
buf[i] = byte(d) | ||
} else if byte(d) != 0 { | ||
panic("math/big: buffer too small to fit value") | ||
} | ||
d >>= 8 | ||
} | ||
} | ||
|
||
return buf | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
//+build go1.15 | ||
|
||
package jwt | ||
|
||
import ( | ||
"crypto/ecdsa" | ||
"crypto/rand" | ||
) | ||
|
||
// Implements the Sign method from SigningMethod | ||
// For this signing method, key must be an ecdsa.PrivateKey struct | ||
func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) { | ||
// Get the key | ||
var ecdsaKey *ecdsa.PrivateKey | ||
switch k := key.(type) { | ||
case *ecdsa.PrivateKey: | ||
ecdsaKey = k | ||
default: | ||
return "", ErrInvalidKeyType | ||
} | ||
|
||
// Create the hasher | ||
if !m.Hash.Available() { | ||
return "", ErrHashUnavailable | ||
} | ||
|
||
hasher := m.Hash.New() | ||
hasher.Write([]byte(signingString)) | ||
|
||
// Sign the string and return r, s | ||
if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil { | ||
curveBits := ecdsaKey.Curve.Params().BitSize | ||
|
||
if m.CurveBits != curveBits { | ||
return "", ErrInvalidKey | ||
} | ||
|
||
keyBytes := curveBits / 8 | ||
if curveBits%8 > 0 { | ||
keyBytes += 1 | ||
} | ||
|
||
// We serialize the outputs (r and s) into big-endian byte arrays | ||
// padded with zeros on the left to make sure the sizes work out. | ||
// Output must be 2*keyBytes long. | ||
out := make([]byte, 2*keyBytes) | ||
r.FillBytes(out[0:keyBytes]) // r is assigned to the first half of output. | ||
s.FillBytes(out[keyBytes:]) // s is assigned to the second half of output. | ||
|
||
return EncodeSegment(out), nil | ||
} else { | ||
return "", err | ||
} | ||
} |