Skip to content

Commit

Permalink
feat(perf): use byte vs string for components
Browse files Browse the repository at this point in the history
Signed-off-by: Thibault Normand <me@zenithar.org>
  • Loading branch information
Zenithar committed Nov 25, 2022
1 parent 9a456d1 commit df4b88d
Show file tree
Hide file tree
Showing 14 changed files with 178 additions and 169 deletions.
34 changes: 19 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ This go library exposed as `zntr.io/paseto` provides :

> This is used in my OIDC framework [SolID](https://github.com/zntrio/solid).
I removed the JSON part encoding requirement to allow PASETO to be used as a
generic data container. You can still use JSON, but also more bytes oriented
serialization for `message`, `footer` and `implicit-assertion`.

## What is PASETO?

From https://github.com/paragonie/paseto :
Expand All @@ -32,7 +36,7 @@ func main () {
m := []byte("my super secret message")

// Encrypt the token
token, err := pasetov4.Encrypt(rand.Reader, localKey, m, "", "")
token, err := pasetov4.Encrypt(rand.Reader, localKey, m, nil, nil)
if err != nil {
panic(err)
}
Expand All @@ -43,36 +47,36 @@ More examples - [here](example_test.go)

## Benchmarks

> Go version 1.19.3 / Mac M1
### V3

```sh
$ go test -bench=. -test.benchtime=1s
goos: darwin
goarch: amd64
goarch: arm64
pkg: zntr.io/paseto/v3
cpu: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
Benchmark_Paseto_Encrypt-16 95533 12378 ns/op 9616 B/op 78 allocs/op
Benchmark_Paseto_Decrypt-16 108386 11064 ns/op 8488 B/op 71 allocs/op
Benchmark_Paseto_Sign-16 360 3370568 ns/op 1718026 B/op 14190 allocs/op
Benchmark_Paseto_Verify-16 186 6457398 ns/op 3476564 B/op 28712 allocs/op
Benchmark_Paseto_Encrypt-10 75150 15071 ns/op 9328 B/op 76 allocs/op
Benchmark_Paseto_Decrypt-10 82350 14535 ns/op 8200 B/op 69 allocs/op
Benchmark_Paseto_Sign-10 7507 159817 ns/op 10004 B/op 101 allocs/op
Benchmark_Paseto_Verify-10 1945 614350 ns/op 3770 B/op 61 allocs/op
PASS
ok zntr.io/paseto/v3 6.361s
ok zntr.io/paseto/v3 5.276s
```

### V4

```sh
$ go test -bench=. -test.benchtime=1s
goos: darwin
goarch: amd64
goarch: arm64
pkg: zntr.io/paseto/v4
cpu: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
Benchmark_Paseto_Encrypt-16 317936 3437 ns/op 3536 B/op 29 allocs/op
Benchmark_Paseto_Decrypt-16 459136 2484 ns/op 2448 B/op 22 allocs/op
Benchmark_Paseto_Sign-16 51328 23316 ns/op 1672 B/op 18 allocs/op
Benchmark_Paseto_Verify-16 22741 52872 ns/op 744 B/op 13 allocs/op
Benchmark_Paseto_Encrypt-10 423649 2823 ns/op 3296 B/op 29 allocs/op
Benchmark_Paseto_Decrypt-10 503470 2389 ns/op 2208 B/op 22 allocs/op
Benchmark_Paseto_Sign-10 46567 25378 ns/op 1720 B/op 17 allocs/op
Benchmark_Paseto_Verify-10 22294 53853 ns/op 792 B/op 12 allocs/op
PASS
ok zntr.io/paseto/v4 5.624s
ok zntr.io/paseto/v4 6.723s
```

## License
Expand Down
22 changes: 11 additions & 11 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func ExamplePasetoV4LocalWithoutFooter() {
m := []byte("my super secret message")

// Encrypt the token
token, err := pasetov4.Encrypt(deterministicSeedForTest, localKey, m, "", "")
token, err := pasetov4.Encrypt(deterministicSeedForTest, localKey, m, nil, nil)
if err != nil {
panic(err)
}
Expand All @@ -63,10 +63,10 @@ func ExamplePasetoV4LocalWithFooter() {

// The footer is public and not encrypted but protected by integrity check.
// You can use it to transport information about the token context.
footer := `{"kid":"1234567890"}`
footer := []byte(`{"kid":"1234567890"}`)

// Encrypt the token
token, err := pasetov4.Encrypt(deterministicSeedForTest, localKey, m, footer, "")
token, err := pasetov4.Encrypt(deterministicSeedForTest, localKey, m, footer, nil)
if err != nil {
panic(err)
}
Expand All @@ -87,11 +87,11 @@ func ExamplePasetoV4LocalWithFooterAndImplicitAssertions() {

// Prepare the message
m := []byte("my super secret message")
footer := `{"kid":"1234567890"}`
footer := []byte(`{"kid":"1234567890"}`)

// Assertions are informations not published in the token but kept by the producer
// and used during the token integrity check.
assertions := `{"user_id":"1234567890"}`
assertions := []byte(`{"user_id":"1234567890"}`)

// Encrypt the token
token, err := pasetov4.Encrypt(deterministicSeedForTest, localKey, m, footer, assertions)
Expand All @@ -117,11 +117,11 @@ func ExamplePasetoV4LocalDecrypt() {
input := []byte("v4.local.dGVzdHMtMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTZ-qF7cj1LApZxpU5R2qdaX9Ox9NaKxnci6ObPVawSbAlqcRdmSDrklvbUqNGk61-tuOKJ0vkFQ.eyJraWQiOiIxMjM0NTY3ODkwIn0")

// Expected footer value.
footer := `{"kid":"1234567890"}`
footer := []byte(`{"kid":"1234567890"}`)

// Assertions are informations not published in the token but kept by the producer
// and used during the token integrity check.
assertions := `{"user_id":"1234567890"}`
assertions := []byte(`{"user_id":"1234567890"}`)

m, err := pasetov4.Decrypt(localKey, input, footer, assertions)
if err != nil {
Expand All @@ -145,8 +145,8 @@ func ExamplePasetoV4PublicSign() {

// Prepare the message
m := []byte("my super secret message")
footer := `{"kid":"1234567890"}`
assertions := `{"user_id":"1234567890"}`
footer := []byte(`{"kid":"1234567890"}`)
assertions := []byte(`{"user_id":"1234567890"}`)

// Sign the token
token, err := pasetov4.Sign(m, sk, footer, assertions)
Expand All @@ -170,8 +170,8 @@ func ExamplePasetoV4PublicVerify() {

// Prepare the message
input := []byte("v4.public.bXkgc3VwZXIgc2VjcmV0IG1lc3NhZ2UbOO-zu6XQbbhmDj0IUEjrmLS_TK1vM69D3pmdbUJmSa7A4c0qjEi9q-DQiMD6UUtbGEMXA1z9zdRskpGfStQH.eyJraWQiOiIxMjM0NTY3ODkwIn0")
footer := `{"kid":"1234567890"}`
assertions := `{"user_id":"1234567890"}`
footer := []byte(`{"kid":"1234567890"}`)
assertions := []byte(`{"user_id":"1234567890"}`)

// Sign the token
m, err := pasetov4.Verify(input, pk, footer, assertions)
Expand Down
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
module zntr.io/paseto

go 1.18
go 1.19

require (
github.com/stretchr/testify v1.7.1
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
github.com/stretchr/testify v1.8.1
golang.org/x/crypto v0.3.0
)

require (
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
golang.org/x/sys v0.2.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
17 changes: 11 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
4 changes: 2 additions & 2 deletions v3/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ func kdf(key *LocalKey, n []byte) (ek, n2, ak []byte, err error) {
return ek, n2, ak, nil
}

func mac(ak []byte, h string, n, c []byte, f, i string) ([]byte, error) {
func mac(ak, h, n, c, f, i []byte) ([]byte, error) {
// Compute pre-authentication message
preAuth, err := common.PreAuthenticationEncoding([]byte(h), n, c, []byte(f), []byte(i))
preAuth, err := common.PreAuthenticationEncoding([]byte(h), n, c, f, i)
if err != nil {
return nil, fmt.Errorf("unable to compute pre-authentication content: %w", err)
}
Expand Down
14 changes: 7 additions & 7 deletions v3/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func LocalKeyFromSeed(seed []byte) (*LocalKey, error) {

// PASETO v3 symmetric encryption primitive.
// https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version3.md#encrypt
func Encrypt(r io.Reader, key *LocalKey, m []byte, f, i string) ([]byte, error) {
func Encrypt(r io.Reader, key *LocalKey, m, f, i []byte) ([]byte, error) {
// Check arguments
if key == nil {
return nil, errors.New("paseto: key is nil")
Expand Down Expand Up @@ -90,7 +90,7 @@ func Encrypt(r io.Reader, key *LocalKey, m []byte, f, i string) ([]byte, error)
ciph.XORKeyStream(c, m)

// Compute MAC
t, err := mac(ak, LocalPrefix, n[:], c, f, i)
t, err := mac(ak, []byte(LocalPrefix), n[:], c, f, i)
if err != nil {
return nil, fmt.Errorf("paseto: unable to compute MAC: %w", err)
}
Expand All @@ -107,7 +107,7 @@ func Encrypt(r io.Reader, key *LocalKey, m []byte, f, i string) ([]byte, error)

// Assemble final token
final := append([]byte(LocalPrefix), encodedBody...)
if f != "" {
if len(f) > 0 {
// Encode footer as RawURLBase64
encodedFooter := make([]byte, base64.RawURLEncoding.EncodedLen(len(f)))
base64.RawURLEncoding.Encode(encodedFooter, []byte(f))
Expand All @@ -122,7 +122,7 @@ func Encrypt(r io.Reader, key *LocalKey, m []byte, f, i string) ([]byte, error)

// PASETO v3 symmetric decryption primitive
// https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version3.md#decrypt
func Decrypt(key *LocalKey, input []byte, f, i string) ([]byte, error) {
func Decrypt(key *LocalKey, input, f, i []byte) ([]byte, error) {
// Check arguments
if key == nil {
return nil, errors.New("paseto: key is nil")
Expand All @@ -143,7 +143,7 @@ func Decrypt(key *LocalKey, input []byte, f, i string) ([]byte, error) {
input = input[len(LocalPrefix):]

// Check footer usage
if f != "" {
if len(f) > 0 {
// Split the footer and the body
parts := bytes.SplitN(input, []byte("."), 2)
if len(parts) != 2 {
Expand All @@ -157,7 +157,7 @@ func Decrypt(key *LocalKey, input []byte, f, i string) ([]byte, error) {
}

// Compare footer
if !common.SecureCompare([]byte(f), footer) {
if !common.SecureCompare(f, footer) {
return nil, errors.New("paseto: invalid token, footer mismatch")
}

Expand All @@ -183,7 +183,7 @@ func Decrypt(key *LocalKey, input []byte, f, i string) ([]byte, error) {
}

// Compute MAC
t2, err := mac(ak, LocalPrefix, n, c, f, i)
t2, err := mac(ak, []byte(LocalPrefix), n, c, f, i)
if err != nil {
return nil, fmt.Errorf("paseto: unable to compute MAC: %w", err)
}
Expand Down
Loading

0 comments on commit df4b88d

Please sign in to comment.