-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use cosmosDB in the gateway and encrypt data with encryption key gene…
…rated inside the enclave (#2104)
- Loading branch information
Showing
24 changed files
with
766 additions
and
439 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,13 @@ | ||
package common | ||
|
||
type AccountDB struct { | ||
AccountAddress []byte | ||
Signature []byte | ||
SignatureType int | ||
type GWUserDB struct { | ||
UserId []byte `json:"userId"` | ||
PrivateKey []byte `json:"privateKey"` | ||
Accounts []GWAccountDB `json:"accounts"` | ||
} | ||
|
||
type UserDB struct { | ||
UserID []byte | ||
PrivateKey []byte | ||
type GWAccountDB struct { | ||
AccountAddress []byte `json:"accountAddress"` | ||
Signature []byte `json:"signature"` | ||
SignatureType int `json:"signatureType"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package encryption | ||
|
||
import ( | ||
"crypto/aes" | ||
"crypto/cipher" | ||
"crypto/hmac" | ||
"crypto/rand" | ||
"crypto/sha256" | ||
"errors" | ||
"fmt" | ||
"io" | ||
) | ||
|
||
// Encryptor provides AES-GCM encryption/decryption with the following characteristics: | ||
// - Uses AES-256-GCM (Galois/Counter Mode) with a 32-byte key | ||
// - Generates a random 12-byte nonce for each encryption operation using crypto/rand | ||
// - The nonce is prepended to the ciphertext output from Encrypt() and is generated | ||
// using crypto/rand.Reader for cryptographically secure random values | ||
// | ||
// Additionally provides HMAC-SHA256 hashing functionality: | ||
// - Uses the same 32-byte key as the encryption operations | ||
// - Generates a 32-byte (256-bit) message authentication code | ||
// - Suitable for creating secure message digests and verifying data integrity | ||
type Encryptor struct { | ||
gcm cipher.AEAD | ||
key []byte | ||
} | ||
|
||
func NewEncryptor(key []byte) (*Encryptor, error) { | ||
if len(key) != 32 { | ||
return nil, fmt.Errorf("key must be 32 bytes long") | ||
} | ||
|
||
block, err := aes.NewCipher(key) | ||
if err != nil { | ||
return nil, err | ||
} | ||
gcm, err := cipher.NewGCM(block) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &Encryptor{gcm: gcm, key: key}, nil | ||
} | ||
|
||
func (e *Encryptor) Encrypt(plaintext []byte) ([]byte, error) { | ||
nonce := make([]byte, e.gcm.NonceSize()) | ||
if _, err := io.ReadFull(rand.Reader, nonce); err != nil { | ||
return nil, err | ||
} | ||
return e.gcm.Seal(nonce, nonce, plaintext, nil), nil | ||
} | ||
|
||
func (e *Encryptor) Decrypt(ciphertext []byte) ([]byte, error) { | ||
if len(ciphertext) < e.gcm.NonceSize() { | ||
return nil, errors.New("ciphertext too short") | ||
} | ||
nonce, ciphertext := ciphertext[:e.gcm.NonceSize()], ciphertext[e.gcm.NonceSize():] | ||
return e.gcm.Open(nil, nonce, ciphertext, nil) | ||
} | ||
|
||
func (e *Encryptor) HashWithHMAC(data []byte) []byte { | ||
h := hmac.New(sha256.New, e.key) | ||
h.Write(data) | ||
return h.Sum(nil) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package encryption | ||
|
||
import ( | ||
"bytes" | ||
"crypto/rand" | ||
"testing" | ||
) | ||
|
||
func TestNewEncryptor(t *testing.T) { | ||
key := make([]byte, 32) // 256-bit key | ||
_, err := rand.Read(key) | ||
if err != nil { | ||
t.Fatalf("Failed to generate random key: %v", err) | ||
} | ||
|
||
encryptor, err := NewEncryptor(key) | ||
if err != nil { | ||
t.Fatalf("NewEncryptor failed: %v", err) | ||
} | ||
|
||
if encryptor == nil { | ||
t.Fatal("NewEncryptor returned nil") | ||
} | ||
} | ||
|
||
func TestEncryptDecrypt(t *testing.T) { | ||
key := make([]byte, 32) // 256-bit key | ||
_, err := rand.Read(key) | ||
if err != nil { | ||
t.Fatalf("Failed to generate random key: %v", err) | ||
} | ||
|
||
encryptor, err := NewEncryptor(key) | ||
if err != nil { | ||
t.Fatalf("NewEncryptor failed: %v", err) | ||
} | ||
|
||
plaintext := []byte("Hello, World!") | ||
|
||
ciphertext, err := encryptor.Encrypt(plaintext) | ||
if err != nil { | ||
t.Fatalf("Encryption failed: %v", err) | ||
} | ||
|
||
decrypted, err := encryptor.Decrypt(ciphertext) | ||
if err != nil { | ||
t.Fatalf("Decryption failed: %v", err) | ||
} | ||
|
||
if !bytes.Equal(plaintext, decrypted) { | ||
t.Fatalf("Decrypted text does not match original plaintext") | ||
} | ||
} | ||
|
||
func TestEncryptDecryptEmptyString(t *testing.T) { | ||
key := make([]byte, 32) // 256-bit key | ||
_, err := rand.Read(key) | ||
if err != nil { | ||
t.Fatalf("Failed to generate random key: %v", err) | ||
} | ||
|
||
encryptor, err := NewEncryptor(key) | ||
if err != nil { | ||
t.Fatalf("NewEncryptor failed: %v", err) | ||
} | ||
|
||
plaintext := []byte("") | ||
|
||
ciphertext, err := encryptor.Encrypt(plaintext) | ||
if err != nil { | ||
t.Fatalf("Encryption of empty string failed: %v", err) | ||
} | ||
|
||
decrypted, err := encryptor.Decrypt(ciphertext) | ||
if err != nil { | ||
t.Fatalf("Decryption of empty string failed: %v", err) | ||
} | ||
|
||
if !bytes.Equal(plaintext, decrypted) { | ||
t.Fatalf("Decrypted empty string does not match original") | ||
} | ||
} | ||
|
||
func TestDecryptInvalidCiphertext(t *testing.T) { | ||
key := make([]byte, 32) // 256-bit key | ||
_, err := rand.Read(key) | ||
if err != nil { | ||
t.Fatalf("Failed to generate random key: %v", err) | ||
} | ||
|
||
encryptor, err := NewEncryptor(key) | ||
if err != nil { | ||
t.Fatalf("NewEncryptor failed: %v", err) | ||
} | ||
|
||
invalidCiphertext := []byte("This is not a valid ciphertext") | ||
|
||
_, err = encryptor.Decrypt(invalidCiphertext) | ||
if err == nil { | ||
t.Fatal("Decryption of invalid ciphertext should have failed, but didn't") | ||
} | ||
} | ||
|
||
func TestNewEncryptorInvalidKeySize(t *testing.T) { | ||
invalidKey := make([]byte, 31) // Invalid key size (not 16, 24, or 32 bytes) | ||
_, err := rand.Read(invalidKey) | ||
if err != nil { | ||
t.Fatalf("Failed to generate random key: %v", err) | ||
} | ||
|
||
_, err = NewEncryptor(invalidKey) | ||
if err == nil { | ||
t.Fatal("NewEncryptor should have failed with invalid key size, but didn't") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.