init: v1.0.0
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
package blockmode_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm4"
|
||||
"xdx.jelly/xgcl/utils/blockmode"
|
||||
)
|
||||
|
||||
// sm4_GCM模式
|
||||
var sm4GCMTests = []struct {
|
||||
key, nonce, plaintext, ad, result string
|
||||
}{
|
||||
{
|
||||
"11754cd72aec309bf52f7687212e8957",
|
||||
"3c819d9a9bed087615030b65", // nonce should be 12 bytes.
|
||||
"plaintext",
|
||||
"additional message not need encrypt, empty is ok",
|
||||
"6111f78f2f82b913c20e333160bfec034c3720ac133a6203b1",
|
||||
},
|
||||
}
|
||||
|
||||
func TestSM4Speed(t *testing.T) {
|
||||
key, err := hex.DecodeString("12345678123456781234567812345678")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
block, err := sm4.NewCipher(key)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
gcm, err := blockmode.NewGCM(blockmode.Wrap(block))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
nonce, err := hex.DecodeString("123456781234567812345678")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
plaintext := grand.GetRandom(1024 * 1024)
|
||||
ad := []byte("additional message not need encrypt, empty is ok")
|
||||
ct2 := make([]byte, 0, 1024*1024+gcm.Overhead())
|
||||
cnt := 100
|
||||
start := time.Now()
|
||||
for i := 0; i < cnt; i++ {
|
||||
err = gcm.EncryptInit(nonce)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
gcm.SpecifyADD(ad)
|
||||
ct2, err := gcm.EncryptUpdate(ct2, plaintext)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ct2, err = gcm.EncryptFinal(ct2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
end := time.Now()
|
||||
elapsed := end.Sub(start)
|
||||
fmt.Printf("%f Bps\n", float64(len(plaintext)*cnt)/1024/1024*1000/float64(elapsed.Milliseconds()))
|
||||
|
||||
}
|
||||
|
||||
func TestSM4GCM(t *testing.T) {
|
||||
for i, test := range sm4GCMTests {
|
||||
key, _ := hex.DecodeString(test.key)
|
||||
|
||||
block, _ := sm4.NewCipher(key)
|
||||
gcm, err := blockmode.NewGCM(blockmode.Wrap(block))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
nonce, _ := hex.DecodeString(test.nonce)
|
||||
plaintext := []byte(test.plaintext)
|
||||
|
||||
ad := []byte(test.ad)
|
||||
|
||||
// 提前分配好空间
|
||||
for i := 0; i < gcm.Overhead(); i++ {
|
||||
plaintext = append(plaintext, 0)
|
||||
}
|
||||
plaintext = plaintext[:len(plaintext)-gcm.Overhead()]
|
||||
|
||||
ct := gcm.Seal(plaintext[:0], nonce, plaintext, ad)
|
||||
|
||||
if ctHex := hex.EncodeToString(ct); ctHex != test.result {
|
||||
t.Errorf("#%d: got %s, want %s", i, ctHex, test.result)
|
||||
continue
|
||||
}
|
||||
|
||||
plaintext, err = gcm.Open(ct[:0], nonce, ct, ad)
|
||||
if err != nil {
|
||||
t.Errorf("#%d: Open failed", i)
|
||||
continue
|
||||
}
|
||||
|
||||
if !bytes.Equal(plaintext, []byte(test.plaintext)) {
|
||||
t.Errorf("#%d: plaintext's don't match: got %x vs %x", i, test.plaintext, plaintext)
|
||||
continue
|
||||
}
|
||||
|
||||
// if ad, nonce, ct was changed, return err
|
||||
if len(ad) > 0 {
|
||||
ad[0] ^= 0x80
|
||||
if _, err := gcm.Open(nil, nonce, ct, ad); err == nil {
|
||||
t.Errorf("#%d: Open was successful after altering additional data", i)
|
||||
}
|
||||
ad[0] ^= 0x80
|
||||
}
|
||||
|
||||
nonce[0] ^= 0x80
|
||||
if _, err := gcm.Open(nil, nonce, ct, ad); err == nil {
|
||||
t.Errorf("#%d: Open was successful after altering nonce", i)
|
||||
}
|
||||
nonce[0] ^= 0x80
|
||||
|
||||
ct[0] ^= 0x80
|
||||
if _, err := gcm.Open(nil, nonce, ct, ad); err == nil {
|
||||
t.Errorf("#%d: Open was successful after altering ciphertext", i)
|
||||
}
|
||||
ct[0] ^= 0x80
|
||||
}
|
||||
}
|
||||
|
||||
func TestGcmUpdate(t *testing.T) {
|
||||
test := sm4GCMTests[0]
|
||||
key, _ := hex.DecodeString(test.key)
|
||||
|
||||
block, _ := sm4.NewCipher(key)
|
||||
gcm, err := blockmode.NewGCM(blockmode.Wrap(block))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
nonce, _ := hex.DecodeString(test.nonce)
|
||||
plaintext := grand.GetRandom(0)
|
||||
ad := []byte(test.ad)
|
||||
ct1 := gcm.Seal(nil, nonce, plaintext, ad)
|
||||
|
||||
ct2 := make([]byte, 0, 116)
|
||||
err = gcm.EncryptInit(nonce)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
gcm.SpecifyADD(ad)
|
||||
for i := range plaintext {
|
||||
ct2, err = gcm.EncryptUpdate(ct2, []byte{plaintext[i]})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
ct2, err = gcm.EncryptFinal(ct2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(ct1, ct2) {
|
||||
t.Errorf("Seal failed")
|
||||
}
|
||||
|
||||
if err = gcm.DecryptInit(nonce); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
gcm.SpecifyADD(ad)
|
||||
|
||||
decrypted := make([]byte, 0, len(plaintext))
|
||||
for i := range ct1 {
|
||||
decrypted, err = gcm.DecryptUpdate(decrypted, []byte{ct1[i]})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
decrypted, err = gcm.DecryptFinal(decrypted)
|
||||
if !bytes.Equal(decrypted, plaintext) {
|
||||
t.Fatal("plaintext unequal decrypted plaintext")
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal("auth failed")
|
||||
}
|
||||
}
|
||||
|
||||
func FuzzSm4Gcm(f *testing.F) {
|
||||
nonce := grand.GetRandom(12)
|
||||
key := grand.GetRandom(16)
|
||||
|
||||
block, _ := sm4.NewCipher(key)
|
||||
gcm, err := blockmode.NewGCM(blockmode.Wrap(block))
|
||||
if err != nil {
|
||||
f.Fatal(err)
|
||||
}
|
||||
stdgcm, _ := sm4.NewGCM(key)
|
||||
|
||||
f.Add([]byte{}, []byte{})
|
||||
f.Fuzz(func(t *testing.T, plaintext, ad []byte) {
|
||||
stdct := stdgcm.Seal(nil, nonce, plaintext, ad)
|
||||
ct1 := gcm.Seal(nil, nonce, plaintext, ad)
|
||||
if !bytes.Equal(ct1, stdct) {
|
||||
t.Errorf("Seal failed")
|
||||
}
|
||||
|
||||
if err := gcm.EncryptInit(nonce); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// if additional data is empty, then call
|
||||
// gcm.SpecifyADD(nil)
|
||||
gcm.SpecifyADD(ad)
|
||||
|
||||
ct2, err := gcm.EncryptUpdate(nil, plaintext[:len(plaintext)/2])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, p := range plaintext[len(plaintext)/2:] {
|
||||
if ct2, err = gcm.EncryptUpdate(ct2, []byte{p}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
ct2, err = gcm.EncryptFinal(ct2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(ct2, stdct) {
|
||||
t.Errorf("Encrypt failed")
|
||||
}
|
||||
|
||||
pt1, err1 := gcm.Open(nil, nonce, ct1, ad)
|
||||
if err1 != nil {
|
||||
t.Errorf("Open faile: %v\n", err1)
|
||||
}
|
||||
if err := gcm.DecryptInit(nonce); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
gcm.SpecifyADD(ad)
|
||||
|
||||
pt2, err := gcm.DecryptUpdate(nil, ct2[:len(ct2)/2])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, p := range ct2[len(ct2)/2:] {
|
||||
if pt2, err = gcm.DecryptUpdate(pt2, []byte{p}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
pt2, err = gcm.DecryptFinal(pt2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(pt2, plaintext) {
|
||||
t.Errorf("Decrypt failed")
|
||||
}
|
||||
|
||||
if !bytes.Equal(pt1, plaintext) {
|
||||
t.Errorf("Open failed")
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user