Skip to content

Commit

Permalink
Add back support for Go 1.14
Browse files Browse the repository at this point in the history
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
zeripath committed Aug 1, 2021
1 parent 4bbdd8a commit 1c57368
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 47 deletions.
47 changes: 0 additions & 47 deletions ecdsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package jwt
import (
"crypto"
"crypto/ecdsa"
"crypto/rand"
"errors"
"math/big"
)
Expand Down Expand Up @@ -94,49 +93,3 @@ func (m *SigningMethodECDSA) Verify(signingString, signature string, key interfa

return ErrECDSAVerification
}

// 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
}
}
77 changes: 77 additions & 0 deletions ecdsa_go1.14.go
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
}
54 changes: 54 additions & 0 deletions ecdsa_go1.15.go
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
}
}

0 comments on commit 1c57368

Please sign in to comment.