-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tests in this file have been order dependent. I broke those dependencies by introducing few additional lines of code in each an every one. And the initHistoryOpts now requires passing pn, so maybe whoever decide to write new tests will realize that it might be nice to create new pubnub and new config instead of reusing them across every test. Co-authored-by: Mateusz Dahlke <[email protected]>
- Loading branch information
Showing
49 changed files
with
2,141 additions
and
2,673 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package crypto | ||
|
||
import ( | ||
"crypto/aes" | ||
"crypto/cipher" | ||
"crypto/sha256" | ||
"errors" | ||
"fmt" | ||
"io" | ||
) | ||
|
||
type aesCbcCryptor struct { | ||
block cipher.Block | ||
} | ||
|
||
func NewAesCbcCryptor(cipherKey string) (ExtendedCryptor, error) { | ||
block, e := aesCipher(cipherKey) | ||
if e != nil { | ||
return nil, e | ||
} | ||
|
||
return &aesCbcCryptor{ | ||
block: block, | ||
}, nil | ||
} | ||
|
||
var crivId = "ACRH" | ||
|
||
func (c *aesCbcCryptor) Id() string { | ||
return crivId | ||
} | ||
|
||
func (c *aesCbcCryptor) Encrypt(message []byte) (*EncryptedData, error) { | ||
message = padWithPKCS7(message) | ||
iv := generateIV(aes.BlockSize) | ||
blockmode := cipher.NewCBCEncrypter(c.block, iv) | ||
|
||
encryptedBytes := make([]byte, len(message)) | ||
blockmode.CryptBlocks(encryptedBytes, message) | ||
|
||
return &EncryptedData{ | ||
Metadata: iv, | ||
Data: encryptedBytes, | ||
}, nil | ||
} | ||
|
||
func (c *aesCbcCryptor) Decrypt(encryptedData *EncryptedData) (r []byte, e error) { | ||
decrypter := cipher.NewCBCDecrypter(c.block, encryptedData.Metadata) | ||
//to handle decryption errors | ||
defer func() { | ||
if rec := recover(); rec != nil { | ||
r, e = nil, fmt.Errorf("%s", rec) | ||
} | ||
}() | ||
|
||
if len(encryptedData.Data)%16 != 0 { | ||
return nil, fmt.Errorf("encrypted data length should be divisible by block size") | ||
} | ||
|
||
decrypted := make([]byte, len(encryptedData.Data)) | ||
decrypter.CryptBlocks(decrypted, encryptedData.Data) | ||
return unpadPKCS7(decrypted) | ||
} | ||
|
||
func (c *aesCbcCryptor) EncryptStream(reader io.Reader) (*EncryptedStreamData, error) { | ||
iv := generateIV(aes.BlockSize) | ||
|
||
return &EncryptedStreamData{ | ||
Metadata: iv, | ||
Reader: newBlockModeEncryptingReader(reader, cipher.NewCBCEncrypter(c.block, iv)), | ||
}, nil | ||
} | ||
|
||
func (c *aesCbcCryptor) DecryptStream(encryptedData *EncryptedStreamData) (io.Reader, error) { | ||
if encryptedData.Metadata == nil { | ||
return nil, errors.New("missing metadata") | ||
} | ||
return newBlockModeDecryptingReader(encryptedData.Reader, cipher.NewCBCDecrypter(c.block, encryptedData.Metadata)), nil | ||
} | ||
|
||
func aesCipher(cipherKey string) (cipher.Block, error) { | ||
hash := sha256.New() | ||
hash.Write([]byte(cipherKey)) | ||
|
||
block, err := aes.NewCipher(hash.Sum(nil)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return block, 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,77 @@ | ||
package crypto | ||
|
||
import ( | ||
"bytes" | ||
"io" | ||
"testing" | ||
"testing/quick" | ||
) | ||
|
||
var defaultPropertyTestConfig = &quick.Config{ | ||
MaxCount: 1000, | ||
} | ||
|
||
func canDecryptEncryptStreamResult(in []byte) bool { | ||
cryptor, e := NewAesCbcCryptor("enigma") | ||
if e != nil { | ||
return false | ||
} | ||
|
||
output, err := cryptor.EncryptStream(bytes.NewReader(in)) | ||
if err != nil { | ||
return false | ||
} | ||
|
||
encrData, err := io.ReadAll(output.Reader) | ||
|
||
decrypted, err := cryptor.Decrypt(&EncryptedData{ | ||
Data: encrData, | ||
Metadata: output.Metadata, | ||
}) | ||
if err != nil { | ||
return false | ||
} | ||
return bytes.Equal(in, decrypted) | ||
} | ||
|
||
func canDecryptStreamEncryptResult(in []byte) bool { | ||
cryptor, e := NewAesCbcCryptor("enigma") | ||
if e != nil { | ||
return false | ||
} | ||
|
||
output, err := cryptor.Encrypt(in) | ||
if err != nil { | ||
println(err.Error()) | ||
return false | ||
} | ||
|
||
decryptingReader, err := cryptor.DecryptStream(&EncryptedStreamData{ | ||
Reader: bytes.NewReader(output.Data), | ||
Metadata: output.Metadata, | ||
}) | ||
if err != nil { | ||
println(err.Error()) | ||
return false | ||
} | ||
|
||
decrypted, err := io.ReadAll(decryptingReader) | ||
if err != nil { | ||
println(err.Error()) | ||
return false | ||
} | ||
|
||
return bytes.Equal(in, decrypted) | ||
} | ||
|
||
func Test_AesCBC_EncryptStream(t *testing.T) { | ||
if err := quick.Check(canDecryptEncryptStreamResult, defaultPropertyTestConfig); err != nil { | ||
t.Error(err) | ||
} | ||
} | ||
|
||
func Test_AesCBC_DecryptStream(t *testing.T) { | ||
if err := quick.Check(canDecryptStreamEncryptResult, defaultPropertyTestConfig); err != nil { | ||
t.Error(err) | ||
} | ||
} |
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,25 @@ | ||
package crypto | ||
|
||
import "io" | ||
|
||
type EncryptedData struct { | ||
Metadata []byte | ||
Data []byte | ||
} | ||
|
||
type Cryptor interface { | ||
Id() string | ||
Encrypt(message []byte) (*EncryptedData, error) | ||
Decrypt(encryptedData *EncryptedData) ([]byte, error) | ||
} | ||
|
||
type EncryptedStreamData struct { | ||
Metadata []byte | ||
Reader io.Reader | ||
} | ||
|
||
type ExtendedCryptor interface { | ||
Cryptor | ||
EncryptStream(reader io.Reader) (*EncryptedStreamData, error) | ||
DecryptStream(encryptedData *EncryptedStreamData) (io.Reader, error) | ||
} |
Oops, something went wrong.