From 900693b830c34ef54b73bf3c1e88175d864719e9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 7 Jan 2021 09:38:30 -0500 Subject: [PATCH] crypto: harden API surface Make it explicit that expiration is not being tested with Decrypt, and test that the expiration is meaningful with DecryptWithExpiration. --- auth/middleware.go | 2 +- crypto/crypto.go | 5 ++++- crypto/crypto_test.go | 2 +- model/cursor.go | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/auth/middleware.go b/auth/middleware.go index 15e8d0e6a1dc84a235cbb5f2908ffadc227dd7b1..14f418e38b77357f882c1dae4fd244a271b7b731 100644 --- a/auth/middleware.go +++ b/auth/middleware.go @@ -215,7 +215,7 @@ type AuthCookie struct { func cookieAuth(cookie *http.Cookie, w http.ResponseWriter, r *http.Request, next http.Handler) { - payload := crypto.Decrypt([]byte(cookie.Value)) + payload := crypto.DecryptWithoutExpiration([]byte(cookie.Value)) if payload == nil { authError(w, "Invalid authentication cookie", http.StatusForbidden) return diff --git a/crypto/crypto.go b/crypto/crypto.go index 025d7453ae5cbbf1bb183ddac277c9d00e5ff874..babfabd68eb55ca09543e27f96b1c120b5ef8b65 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -63,12 +63,15 @@ func Encrypt(payload []byte) []byte { return msg } -func Decrypt(payload []byte) []byte { +func DecryptWithoutExpiration(payload []byte) []byte { return fernet.VerifyAndDecrypt(payload, time.Duration(0), []*fernet.Key{fernetKey}) } func DecryptWithExpiration(payload []byte, expiry time.Duration) []byte { + if expiry == 0 { + panic(fmt.Errorf("DecryptWithExpiration given expiration of zero. Use DecryptWithoutExpiration if you really meant it.")) + } return fernet.VerifyAndDecrypt(payload, expiry, []*fernet.Key{fernetKey}) } diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index eb7e7cad4519715e79e7310690f7259881668b57..7cc93b5a970ff5c81a9d478dd66f948abd23c00a 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -57,7 +57,7 @@ func TestEncrypt(t *testing.T) { assert.NotNil(t, enc) assert.NotEqual(t, enc, []byte("Hello, world!")) - dec := Decrypt(enc) + dec := DecryptWithoutExpiration(enc) assert.NotNil(t, dec) assert.Equal(t, dec, []byte("Hello, world!")) } diff --git a/model/cursor.go b/model/cursor.go index 6f87b229b3e1cf24393d349936efa98036998052..3dffa2029ef27222f26198debfee151afbfd806c 100644 --- a/model/cursor.go +++ b/model/cursor.go @@ -20,7 +20,7 @@ func (cur *Cursor) UnmarshalGQL(v interface{}) error { if !ok { return fmt.Errorf("cursor must be strings") } - plain := crypto.Decrypt([]byte(enc)) + plain := crypto.DecryptWithoutExpiration([]byte(enc)) if plain == nil { return fmt.Errorf("Invalid cursor") }