You've already forked oauth2-proxy
mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2025-12-03 22:59:10 +02:00
Add GCM Cipher support
During the upcoming encoded session refactor, AES GCM is ideal to use as the Redis (and other DB like stores) encryption wrapper around the session because each session is encrypted with a distinct secret that is passed by the session ticket.
This commit is contained in:
@@ -134,17 +134,96 @@ func TestEncodeAndDecodeAccessTokenB64(t *testing.T) {
|
||||
assert.Equal(t, []byte(token), decoded)
|
||||
}
|
||||
|
||||
func TestEncryptAndDecryptBase64(t *testing.T) {
|
||||
func TestEncryptAndDecrypt(t *testing.T) {
|
||||
var err error
|
||||
|
||||
// Test our 3 cipher types
|
||||
for _, initCipher := range []func([]byte) (Cipher, error){NewCipher, NewCFBCipher, NewGCMCipher} {
|
||||
// Test all 3 valid AES sizes
|
||||
for _, secretSize := range []int{16, 24, 32} {
|
||||
secret := make([]byte, secretSize)
|
||||
_, err = io.ReadFull(rand.Reader, secret)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
c, err := initCipher(secret)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
// Test various sizes sessions might be
|
||||
for _, dataSize := range []int{10, 100, 1000, 5000, 10000} {
|
||||
data := make([]byte, dataSize)
|
||||
_, err := io.ReadFull(rand.Reader, data)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
encrypted, err := c.Encrypt(data)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.NotEqual(t, encrypted, data)
|
||||
|
||||
decrypted, err := c.Decrypt(encrypted)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, data, decrypted)
|
||||
assert.NotEqual(t, encrypted, decrypted)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecryptWrongSecret(t *testing.T) {
|
||||
secret1 := []byte("0123456789abcdefghijklmnopqrstuv")
|
||||
secret2 := []byte("9876543210abcdefghijklmnopqrstuv")
|
||||
|
||||
// Test CFB & Base64 (GCM is authenticated, it errors differently)
|
||||
for _, initCipher := range []func([]byte) (Cipher, error){NewCipher, NewCFBCipher} {
|
||||
c1, err := initCipher(secret1)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
c2, err := initCipher(secret2)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
data := []byte("f3928pufm982374dj02y485dsl34890u2t9nd4028s94dm58y2394087dhmsyt29h8df")
|
||||
|
||||
ciphertext, err := c1.Encrypt(data)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
wrongData, err := c2.Decrypt(ciphertext)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.NotEqual(t, data, wrongData)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecryptGCMWrongSecret(t *testing.T) {
|
||||
secret1 := []byte("0123456789abcdefghijklmnopqrstuv")
|
||||
secret2 := []byte("9876543210abcdefghijklmnopqrstuv")
|
||||
|
||||
c1, err := NewGCMCipher(secret1)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
c2, err := NewGCMCipher(secret2)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
data := []byte("f3928pufm982374dj02y485dsl34890u2t9nd4028s94dm58y2394087dhmsyt29h8df")
|
||||
|
||||
ciphertext, err := c1.Encrypt(data)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
// GCM is authenticated - this should lead to message authentication failed
|
||||
_, err = c2.Decrypt(ciphertext)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestIntermixCiphersErrors(t *testing.T) {
|
||||
var err error
|
||||
|
||||
// Encrypt with GCM, Decrypt with CFB: Results in Garbage data
|
||||
// Test all 3 valid AES sizes
|
||||
for _, secretSize := range []int{16, 24, 32} {
|
||||
secret := make([]byte, secretSize)
|
||||
_, err = io.ReadFull(rand.Reader, secret)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
// NewCipher creates a Base64 wrapper of CFBCipher
|
||||
c, err := NewCipher(secret)
|
||||
gcm, err := NewGCMCipher(secret)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
cfb, err := NewCFBCipher(secret)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
// Test various sizes sessions might be
|
||||
@@ -153,48 +232,29 @@ func TestEncryptAndDecryptBase64(t *testing.T) {
|
||||
_, err := io.ReadFull(rand.Reader, data)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
encrypted, err := c.Encrypt(data)
|
||||
encrypted, err := gcm.Encrypt(data)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.NotEqual(t, encrypted, data)
|
||||
|
||||
decrypted, err := c.Decrypt(encrypted)
|
||||
decrypted, err := cfb.Decrypt(encrypted)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, data, decrypted)
|
||||
// Data is mangled
|
||||
assert.NotEqual(t, data, decrypted)
|
||||
assert.NotEqual(t, encrypted, decrypted)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecryptBase64WrongSecret(t *testing.T) {
|
||||
var err error
|
||||
|
||||
secret1 := []byte("0123456789abcdefghijklmnopqrstuv")
|
||||
secret2 := []byte("9876543210abcdefghijklmnopqrstuv")
|
||||
|
||||
c1, err := NewCipher(secret1)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
c2, err := NewCipher(secret2)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
data := []byte("f3928pufm982374dj02y485dsl34890u2t9nd4028s94dm58y2394087dhmsyt29h8df")
|
||||
|
||||
ciphertext, err := c1.Encrypt(data)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
wrongData, err := c2.Decrypt(ciphertext)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.NotEqual(t, data, wrongData)
|
||||
}
|
||||
|
||||
func TestEncryptAndDecryptCFB(t *testing.T) {
|
||||
var err error
|
||||
|
||||
// Encrypt with CFB, Decrypt with GCM: Results in errors
|
||||
// Test all 3 valid AES sizes
|
||||
for _, secretSize := range []int{16, 24, 32} {
|
||||
secret := make([]byte, secretSize)
|
||||
_, err = io.ReadFull(rand.Reader, secret)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
c, err := NewCFBCipher(secret)
|
||||
gcm, err := NewGCMCipher(secret)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
cfb, err := NewCFBCipher(secret)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
// Test various sizes sessions might be
|
||||
@@ -203,38 +263,17 @@ func TestEncryptAndDecryptCFB(t *testing.T) {
|
||||
_, err := io.ReadFull(rand.Reader, data)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
encrypted, err := c.Encrypt(data)
|
||||
encrypted, err := cfb.Encrypt(data)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.NotEqual(t, encrypted, data)
|
||||
|
||||
decrypted, err := c.Decrypt(encrypted)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, data, decrypted)
|
||||
// GCM is authenticated - this should lead to message authentication failed
|
||||
_, err = gcm.Decrypt(encrypted)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecryptCFBWrongSecret(t *testing.T) {
|
||||
var err error
|
||||
|
||||
secret1 := []byte("0123456789abcdefghijklmnopqrstuv")
|
||||
secret2 := []byte("9876543210abcdefghijklmnopqrstuv")
|
||||
|
||||
c1, err := NewCFBCipher(secret1)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
c2, err := NewCFBCipher(secret2)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
data := []byte("f3928pufm982374dj02y485dsl34890u2t9nd4028s94dm58y2394087dhmsyt29h8df")
|
||||
|
||||
ciphertext, err := c1.Encrypt(data)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
wrongData, err := c2.Decrypt(ciphertext)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.NotEqual(t, data, wrongData)
|
||||
}
|
||||
|
||||
func TestEncodeIntoAndDecodeIntoAccessToken(t *testing.T) {
|
||||
const secret = "0123456789abcdefghijklmnopqrstuv"
|
||||
c, err := NewCipher([]byte(secret))
|
||||
|
||||
Reference in New Issue
Block a user