Skip to content

Commit

Permalink
jwe/CompactSerialize: improve performance. (#67)
Browse files Browse the repository at this point in the history
Avoid fmt.Sprintf, which is unnecessarily slow. Instead allocate a `[]byte` and write directly to that.
  • Loading branch information
lasiar committed Nov 27, 2023
1 parent 053c9bf commit aa386df
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 12 deletions.
33 changes: 33 additions & 0 deletions encoding.go
Expand Up @@ -189,3 +189,36 @@ func base64URLDecode(value string) ([]byte, error) {
value = strings.TrimRight(value, "=")
return base64.RawURLEncoding.DecodeString(value)
}

func base64EncodeLen(sl []byte) int {
return base64.RawURLEncoding.EncodedLen(len(sl))
}

func base64JoinWithDots(inputs ...[]byte) string {
if len(inputs) == 0 {
return ""
}

// Count of dots.
totalCount := len(inputs) - 1

for _, input := range inputs {
totalCount += base64EncodeLen(input)
}

out := make([]byte, totalCount)
startEncode := 0
for i, input := range inputs {
base64.RawURLEncoding.Encode(out[startEncode:], input)

if i == len(inputs)-1 {
continue
}

startEncode += base64EncodeLen(input)
out[startEncode] = '.'
startEncode++
}

return string(out)
}
14 changes: 7 additions & 7 deletions jwe.go
Expand Up @@ -252,13 +252,13 @@ func (obj JSONWebEncryption) CompactSerialize() (string, error) {

serializedProtected := mustSerializeJSON(obj.protected)

return fmt.Sprintf(
"%s.%s.%s.%s.%s",
base64.RawURLEncoding.EncodeToString(serializedProtected),
base64.RawURLEncoding.EncodeToString(obj.recipients[0].encryptedKey),
base64.RawURLEncoding.EncodeToString(obj.iv),
base64.RawURLEncoding.EncodeToString(obj.ciphertext),
base64.RawURLEncoding.EncodeToString(obj.tag)), nil
return base64JoinWithDots(
serializedProtected,
obj.recipients[0].encryptedKey,
obj.iv,
obj.ciphertext,
obj.tag,
), nil
}

// FullSerialize serializes an object using the full JSON serialization format.
Expand Down
13 changes: 8 additions & 5 deletions jws.go
Expand Up @@ -314,15 +314,18 @@ func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) {
return "", ErrNotSupported
}

serializedProtected := base64.RawURLEncoding.EncodeToString(mustSerializeJSON(obj.Signatures[0].protected))
payload := ""
signature := base64.RawURLEncoding.EncodeToString(obj.Signatures[0].Signature)
serializedProtected := mustSerializeJSON(obj.Signatures[0].protected)

var payload []byte
if !detached {
payload = base64.RawURLEncoding.EncodeToString(obj.payload)
payload = obj.payload
}

return fmt.Sprintf("%s.%s.%s", serializedProtected, payload, signature), nil
return base64JoinWithDots(
serializedProtected,
payload,
obj.Signatures[0].Signature,
), nil
}

// CompactSerialize serializes an object using the compact serialization format.
Expand Down

0 comments on commit aa386df

Please sign in to comment.