Skip to content
This repository has been archived by the owner on Feb 27, 2023. It is now read-only.

Cherry-pick v2 PRs #292

Merged
merged 4 commits into from
Mar 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@ import (
"encoding/binary"
"io"
"math/big"
"regexp"
"strings"
"unicode"

"github.com/square/go-jose/v3/json"
)

var stripWhitespaceRegex = regexp.MustCompile(`\s`)

// Helper function to serialize known-good objects.
// Precondition: value is not a nil pointer.
func mustSerializeJSON(value interface{}) []byte {
Expand All @@ -56,7 +55,16 @@ func mustSerializeJSON(value interface{}) []byte {

// Strip all newlines and whitespace
func stripWhitespace(data string) string {
return stripWhitespaceRegex.ReplaceAllString(data, "")
buf := strings.Builder{}
buf.Grow(len(data))

for _, r := range data {
mbyczkowski marked this conversation as resolved.
Show resolved Hide resolved
if !unicode.IsSpace(r) {
buf.WriteRune(r)
}
}

return buf.String()
mbyczkowski marked this conversation as resolved.
Show resolved Hide resolved
}

// Perform compression based on algorithm
Expand Down
6 changes: 3 additions & 3 deletions jws.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,14 @@ func (sig Signature) mergedHeaders() rawHeader {
}

// Compute data to be signed
func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature) []byte {
func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature) ([]byte, error) {
var authData bytes.Buffer

protectedHeader := new(rawHeader)

if signature.original != nil && signature.original.Protected != nil {
if err := json.Unmarshal(signature.original.Protected.bytes(), protectedHeader); err != nil {
panic(err)
return nil, err
}
authData.WriteString(signature.original.Protected.base64())
} else if signature.protected != nil {
Expand All @@ -134,7 +134,7 @@ func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature
authData.Write(payload)
}

return authData.Bytes()
return authData.Bytes(), nil
}

// parseSignedFull parses a message in full format.
Expand Down
39 changes: 39 additions & 0 deletions jws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ package jose

import (
"crypto/x509"
"encoding/base64"
"strings"
"testing"

"github.com/stretchr/testify/assert"
)

const trustedCA = `
Expand Down Expand Up @@ -649,3 +652,39 @@ func TestDetachedCompactSerialization(t *testing.T) {
t.Fatalf("got '%s', expected '%s'", ser, msg)
}
}

func TestJWSComputeAuthDataBase64(t *testing.T) {
jws := JSONWebSignature{}

_, err := jws.computeAuthData([]byte{0x01}, &Signature{
original: &rawSignatureInfo{
Protected: newBuffer([]byte("{!invalid-json}")),
},
})
// Invalid header, should return error
assert.NotNil(t, err)

payload := []byte{0x01}
encodedPayload := base64.RawURLEncoding.EncodeToString(payload)

b64TrueHeader := newBuffer([]byte(`{"alg":"RSA-OAEP","enc":"A256GCM","b64":true}`))
b64FalseHeader := newBuffer([]byte(`{"alg":"RSA-OAEP","enc":"A256GCM","b64":false}`))

data, err := jws.computeAuthData(payload, &Signature{
original: &rawSignatureInfo{
Protected: b64TrueHeader,
},
})
assert.Nil(t, err)
// Payload should be b64 encoded
assert.Len(t, data, len(b64TrueHeader.base64())+len(encodedPayload)+1)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mnd: Magic number: 1, in detected (from gomnd)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should probably disable gomnd in test files


data, err = jws.computeAuthData(payload, &Signature{
original: &rawSignatureInfo{
Protected: b64FalseHeader,
},
})
assert.Nil(t, err)
// Payload should *not* be b64 encoded
assert.Len(t, data, len(b64FalseHeader.base64())+len(payload)+1)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mnd: Magic number: 1, in detected (from gomnd)

}
2 changes: 1 addition & 1 deletion jwt/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type Expected struct {
Audience Audience
// ID matches the "jti" claim exactly.
ID string
// Time matches the "exp" and "nbf" claims with leeway.
// Time matches the "exp", "nbf" and "iat" claims with leeway.
Time time.Time
}

Expand Down
12 changes: 10 additions & 2 deletions signing.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,11 @@ func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey inter
}
}

input := obj.computeAuthData(payload, &signature)
input, err := obj.computeAuthData(payload, &signature)
if err != nil {
return ErrCryptoFailure
}

alg := headers.getSignatureAlgorithm()
err = verifier.verifyPayload(input, signature.Signature, alg)
if err == nil {
Expand Down Expand Up @@ -421,7 +425,11 @@ outer:
}
}

input := obj.computeAuthData(payload, &signature)
input, err := obj.computeAuthData(payload, &signature)
if err != nil {
continue
}

alg := headers.getSignatureAlgorithm()
err = verifier.verifyPayload(input, signature.Signature, alg)
if err == nil {
Expand Down
11 changes: 11 additions & 0 deletions signing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -583,3 +583,14 @@ func TestSignerB64(t *testing.T) {
t.Errorf("Input/output do not match, got '%s', expected '%s'", output, input)
}
}

func BenchmarkParseSigned(b *testing.B) {
msg := `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`

for i := 0; i < b.N; i++ {
mbyczkowski marked this conversation as resolved.
Show resolved Hide resolved
_, err := ParseSigned(msg)
if err != nil {
b.Errorf("Error on parse: %s", err)
}
}
}