Skip to content

Commit

Permalink
Add top level protocol functions that use V2 as default (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
o1egl authored Jan 18, 2020
1 parent 5f81bc3 commit 6b4348d
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 26 deletions.
48 changes: 23 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,7 @@ $ go get -u github.com/o1egl/paseto
# Usage
This library contains a predefined JsonToken struct for using as payload, but you are free to use any data types and structs you want.

During the encoding process a payload of type string and []byte is used without transformation. For other data types, the library tries to encode the payload to json.

## Use general parser to parse all supported token versions:
```go
b, err := hex.DecodeString("2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0d0a4d494942496a414e42676b71686b6947397730424151454641414f43415138414d49494243674b43415145417878636e47724e4f6136426c41523458707050640d0a746146576946386f7279746c4b534d6a66446831314c687956627a4335416967556b706a457274394d7649482f46384d444a72324f39486b36594b454b574b6f0d0a72333566364b6853303679357a714f722b7a4e34312b39626a52365633322b527345776d5a737a3038375258764e41334e687242633264593647736e57336c5a0d0a34356f5341564a755639553667335a334a574138355972362b6350776134793755632f56726f6d7a674679627355656e33476f724254626a783142384f514a440d0a73652f4b6b6855433655693358384264514f473974523455454775742f6c39703970732b3661474d4c57694357495a54615456784d4f75653133596b777038740d0a3148467635747a6872493055635948687638464a6b315a6435386759464158634e797975737834346e6a6152594b595948646e6b4f6a486e33416b534c4d306b0d0a6c774944415141420d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d")
block, _ := pem.Decode(b)
rsaPubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
v1PublicKey := rsaPubInterface.(*rsa.PublicKey)

b, _ = hex.DecodeString("1eb9dbbbbc047c03fd70604e0071f0987e16b28b757225c11f00415d0e20b1a2")
v2PublicKey := ed25519.PublicKey(b)


var payload JSONToken
var footer string
version, err := paseto.Parse(token, &payload, &footer, symmetricKey, map[paseto.Version]crypto.PublicKey{paseto.V1: v1PublicKey, paseto.V2: v2PublicKey})
```
During the encoding process a payload of type string and []byte is used without transformation. For other data types, the library encodes the payload to json.

## Create token using symmetric key (local mode):
```go
Expand All @@ -84,16 +68,14 @@ jsonToken := paseto.JSONToken{
jsonToken.Set("data", "this is a signed message")
footer := "some footer"

v2 := paseto.NewV2()

// Encrypt data
token, err := v2.Encrypt(symmetricKey, jsonToken, footer)
token, err := paseto.Encrypt(symmetricKey, jsonToken, footer)
// token = "v2.local.E42A2iMY9SaZVzt-WkCi45_aebky4vbSUJsfG45OcanamwXwieieMjSjUkgsyZzlbYt82miN1xD-X0zEIhLK_RhWUPLZc9nC0shmkkkHS5Exj2zTpdNWhrC5KJRyUrI0cupc5qrctuREFLAvdCgwZBjh1QSgBX74V631fzl1IErGBgnt2LV1aij5W3hw9cXv4gtm_jSwsfee9HZcCE0sgUgAvklJCDO__8v_fTY7i_Regp5ZPa7h0X0m3yf0n4OXY9PRplunUpD9uEsXJ_MTF5gSFR3qE29eCHbJtRt0FFl81x-GCsQ9H9701TzEjGehCC6Bhw.c29tZSBmb290ZXI"

// Decrypt data
var newJsonToken paseto.JSONToken
var newFooter string
err := v2.Decrypt(token, symmetricKey, &newJsonToken, &newFooter)
err := paseto.Decrypt(token, symmetricKey, &newJsonToken, &newFooter)
```

## Create token using asymetric key (public mode):
Expand All @@ -115,16 +97,32 @@ jsonToken := paseto.JSONToken{
jsonToken.Set("data", "this is a signed message")
footer := "some footer"

v2 := paseto.NewV2()

// Sign data
token, err := v2.Sign(privateKey, jsonToken, footer)
token, err := paseto.Sign(privateKey, jsonToken, footer)
// token = "v2.public.eyJkYXRhIjoidGhpcyBpcyBhIHNpZ25lZCBtZXNzYWdlIiwiZXhwIjoiMjAxOC0wMy0xMlQxOTowODo1NCswMTowMCJ9Ojv0uXlUNXSFhR88KXb568LheLRdeGy2oILR3uyOM_-b7r7i_fX8aljFYUiF-MRr5IRHMBcWPtM0fmn9SOd6Aw.c29tZSBmb290ZXI"

// Verify data
var newJsonToken paseto.JSONToken
var newFooter string
err := v2.Verify(token, publicKey, &newJsonToken, &newFooter)
err := paseto.Verify(token, publicKey, &newJsonToken, &newFooter)
```

## Use Parse() function to parse all supported token versions:
**IMPORTANT**: Version 1 of protocol is deprecated

```go
b, err := hex.DecodeString("2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0d0a4d494942496a414e42676b71686b6947397730424151454641414f43415138414d49494243674b43415145417878636e47724e4f6136426c41523458707050640d0a746146576946386f7279746c4b534d6a66446831314c687956627a4335416967556b706a457274394d7649482f46384d444a72324f39486b36594b454b574b6f0d0a72333566364b6853303679357a714f722b7a4e34312b39626a52365633322b527345776d5a737a3038375258764e41334e687242633264593647736e57336c5a0d0a34356f5341564a755639553667335a334a574138355972362b6350776134793755632f56726f6d7a674679627355656e33476f724254626a783142384f514a440d0a73652f4b6b6855433655693358384264514f473974523455454775742f6c39703970732b3661474d4c57694357495a54615456784d4f75653133596b777038740d0a3148467635747a6872493055635948687638464a6b315a6435386759464158634e797975737834346e6a6152594b595948646e6b4f6a486e33416b534c4d306b0d0a6c774944415141420d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d")
block, _ := pem.Decode(b)
rsaPubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
v1PublicKey := rsaPubInterface.(*rsa.PublicKey)

b, _ = hex.DecodeString("1eb9dbbbbc047c03fd70604e0071f0987e16b28b757225c11f00415d0e20b1a2")
v2PublicKey := ed25519.PublicKey(b)


var payload JSONToken
var footer string
version, err := paseto.Parse(token, &payload, &footer, symmetricKey, map[paseto.Version]crypto.PublicKey{paseto.V1: v1PublicKey, paseto.V2: v2PublicKey})
```

For more information see *_test.go files.
Expand Down
26 changes: 25 additions & 1 deletion parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,33 @@ var availableVersions = map[Version]Protocol{
VersionV2: NewV2(),
}

// Encrypt encrypts a token with a symmetric key. The key length must be 32.
// Uses V2 protocol as default
func Encrypt(key []byte, payload, footer interface{}) (string, error) {
return NewV2().Encrypt(key, payload, footer)
}

// Decrypt decrypts a token.
// Uses V2 protocol as default.
func Decrypt(token string, key []byte, payload, footer interface{}) error {
return NewV2().Decrypt(token, key, payload, footer)
}

// Sign signs a token with the given private key. The key should be an ed25519.PrivateKey.
// Uses V2 protocol as default.
func Sign(privateKey crypto.PrivateKey, payload, footer interface{}) (string, error) {
return NewV2().Sign(privateKey, payload, footer)
}

// Verify verifies a token against the given public key. The key should be an ed25519.PublicKey.
// Uses V2 protocol as default.
func Verify(token string, publicKey crypto.PublicKey, value, footer interface{}) error {
return NewV2().Verify(token, publicKey, value, footer)
}

// Parse extracts the payload and footer from the token by calling either
// Decrypt() or Verify(), depending on whether the token is public or private.
// To parse public tokens you need to provide a map containing v1 and/or v2
// To parse public tokens you need to provide a map containing V1 and/or V2
// public keys, depending on the version of the token. To parse private tokens
// you need to provide the symmetric key.
func Parse(token string, payload, footer interface{},
Expand Down
76 changes: 76 additions & 0 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,82 @@ import (
"golang.org/x/crypto/ed25519"
)

func TestEncrypt(t *testing.T) {
key := []byte("YELLOW SUBMARINE, BLACK WIZARDRY")
payload := []byte("payload")
footer := []byte("footer")

token, err := Encrypt(key, payload, footer)
if assert.NoError(t, err) {
var (
decryptedPayload []byte
decryptedFooter []byte
)
if err = NewV2().Decrypt(token, key, &decryptedPayload, &decryptedFooter); assert.NoError(t, err) {
assert.Equal(t, payload, decryptedPayload)
assert.Equal(t, footer, decryptedFooter)
}
}
}

func TestDecrypt(t *testing.T) {
key := []byte("YELLOW SUBMARINE, BLACK WIZARDRY")
payload := []byte("payload")
footer := []byte("footer")

token, err := NewV2().Encrypt(key, payload, footer)
if assert.NoError(t, err) {
var (
decryptedPayload []byte
decryptedFooter []byte
)
if err = Decrypt(token, key, &decryptedPayload, &decryptedFooter); assert.NoError(t, err) {
assert.Equal(t, payload, decryptedPayload)
assert.Equal(t, footer, decryptedFooter)
}
}
}

func TestSign(t *testing.T) {
b, _ := hex.DecodeString("b4cbfb43df4ce210727d953e4a713307fa19bb7d9f85041438d9e11b942a37741eb9dbbbbc047c03fd70604e0071f0987e16b28b757225c11f00415d0e20b1a2")
privateKey := ed25519.PrivateKey(b)

payload := []byte("payload")
footer := []byte("footer")

token, err := Sign(privateKey, payload, footer)
if assert.NoError(t, err) {
var (
decryptedPayload []byte
decryptedFooter []byte
)
if err := NewV2().Verify(token, privateKey.Public(), &decryptedPayload, &decryptedFooter); assert.NoError(t, err) {
assert.Equal(t, payload, decryptedPayload)
assert.Equal(t, footer, decryptedFooter)
}
}
}

func TestVerify(t *testing.T) {
b, _ := hex.DecodeString("b4cbfb43df4ce210727d953e4a713307fa19bb7d9f85041438d9e11b942a37741eb9dbbbbc047c03fd70604e0071f0987e16b28b757225c11f00415d0e20b1a2")
privateKey := ed25519.PrivateKey(b)

payload := []byte("payload")
footer := []byte("footer")

token, err := NewV2().Sign(privateKey, payload, footer)
if assert.NoError(t, err) {
var (
decryptedPayload []byte
decryptedFooter []byte
)
if err := Verify(token, privateKey.Public(), &decryptedPayload, &decryptedFooter); assert.NoError(t, err) {
assert.Equal(t, payload, decryptedPayload)
assert.Equal(t, footer, decryptedFooter)
}
}
}

func TestParse(t *testing.T) {
symmetricKey, _ := hex.DecodeString("707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f")

Expand Down

0 comments on commit 6b4348d

Please sign in to comment.