diff --git a/drbg/example_test.go b/drbg/example_test.go new file mode 100644 index 0000000..66d75f6 --- /dev/null +++ b/drbg/example_test.go @@ -0,0 +1,46 @@ +package drbg_test + +import ( + "bytes" + "fmt" + + "github.com/emmansun/gmsm/drbg" +) + +func ExampleNewGmCtrDrbgPrng() { + prng, err := drbg.NewGmCtrDrbgPrng(nil, 32, drbg.SECURITY_LEVEL_TEST, nil) + if err != nil { + panic(err) + } + c := 10 + b := make([]byte, c) + _, err = prng.Read(b) + if err != nil { + fmt.Println("error:", err) + return + } + // The slice should now contain random bytes instead of only zeroes. + fmt.Println(bytes.Equal(b, make([]byte, c))) + + // Output: + // false +} + +func ExampleNewGmHashDrbgPrng() { + prng, err := drbg.NewGmHashDrbgPrng(nil, 32, drbg.SECURITY_LEVEL_TEST, nil) + if err != nil { + panic(err) + } + c := 10 + b := make([]byte, c) + _, err = prng.Read(b) + if err != nil { + fmt.Println("error:", err) + return + } + // The slice should now contain random bytes instead of only zeroes. + fmt.Println(bytes.Equal(b, make([]byte, c))) + + // Output: + // false +} diff --git a/zuc/core.go b/zuc/core.go index 4e5318c..c77c0c9 100644 --- a/zuc/core.go +++ b/zuc/core.go @@ -7,6 +7,11 @@ import ( "math/bits" ) +const ( + IVSize128 = 16 + IVSize256 = 23 +) + // constant D for ZUC-128 var kd = [16]uint32{ 0x44D7, 0x26BC, 0x626B, 0x135E, 0x5789, 0x35E2, 0x7135, 0x09AF, @@ -181,13 +186,13 @@ func newZUCState(key, iv []byte) (*zucState32, error) { default: return nil, fmt.Errorf("zuc: invalid key size %d, we support 16/32 now", k) case 16: // ZUC-128 - if ivLen != 16 { - return nil, fmt.Errorf("zuc: invalid iv size %d, expect 16 in bytes", ivLen) + if ivLen != IVSize128 { + return nil, fmt.Errorf("zuc: invalid iv size %d, expect %d in bytes", ivLen, IVSize128) } state.loadKeyIV16(key, iv) case 32: // ZUC-256 - if ivLen != 23 { - return nil, fmt.Errorf("zuc: invalid iv size %d, expect 23 in bytes", ivLen) + if ivLen != IVSize256 { + return nil, fmt.Errorf("zuc: invalid iv size %d, expect %d in bytes", ivLen, IVSize256) } state.loadKeyIV32(key, iv, zuc256_d0[:]) } diff --git a/zuc/eia.go b/zuc/eia.go index 92d7573..7f81768 100644 --- a/zuc/eia.go +++ b/zuc/eia.go @@ -32,8 +32,8 @@ func NewHash(key, iv []byte) (*ZUC128Mac, error) { default: return nil, fmt.Errorf("zuc/eia: invalid key size %d, expect 16 in bytes", k) case 16: // ZUC-128 - if ivLen != 16 { - return nil, fmt.Errorf("zuc/eia: invalid iv size %d, expect 16 in bytes", ivLen) + if ivLen != IVSize128 { + return nil, fmt.Errorf("zuc/eia: invalid iv size %d, expect %d in bytes", ivLen, IVSize128) } mac.loadKeyIV16(key, iv) } diff --git a/zuc/eia256.go b/zuc/eia256.go index a32306f..99028ca 100644 --- a/zuc/eia256.go +++ b/zuc/eia256.go @@ -40,8 +40,8 @@ func NewHash256(key, iv []byte, tagSize int) (*ZUC256Mac, error) { default: return nil, fmt.Errorf("zuc/eia: invalid key size %d, expect 32 in bytes", k) case 32: // ZUC-256 - if ivLen != 23 { - return nil, fmt.Errorf("zuc/eia: invalid iv size %d, expect 23 in bytes", ivLen) + if ivLen != IVSize256 { + return nil, fmt.Errorf("zuc/eia: invalid iv size %d, expect %d in bytes", ivLen, IVSize256) } mac.loadKeyIV32(key, iv, d) } diff --git a/zuc/example_test.go b/zuc/example_test.go new file mode 100644 index 0000000..c3e976c --- /dev/null +++ b/zuc/example_test.go @@ -0,0 +1,130 @@ +package zuc_test + +import ( + "crypto/rand" + "encoding/hex" + "fmt" + "io" + + "github.com/emmansun/gmsm/zuc" +) + +func ExampleNewCipher() { + // Load your secret key from a safe place and reuse it across multiple + // NewCipher calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + key, _ := hex.DecodeString("6368616e676520746869732070617373") + plaintext := []byte("some plaintext") + + const ivSize = zuc.IVSize128 + // The IV needs to be unique, but not secure. Therefore it's common to + // include it at the beginning of the ciphertext. + ciphertext := make([]byte, ivSize+len(plaintext)) + iv := ciphertext[:ivSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + panic(err) + } + + stream, err := zuc.NewCipher(key, iv) + if err != nil { + panic(err) + } + stream.XORKeyStream(ciphertext[ivSize:], plaintext) + + // It's important to remember that ciphertexts must be authenticated + // (i.e. by using crypto/hmac) as well as being encrypted in order to + // be secure. + + // Stream cipher is the same for both encryption and decryption, so we can + // also decrypt that ciphertext with NewCTR. + + plaintext2 := make([]byte, len(plaintext)) + stream, err = zuc.NewCipher(key, iv) + if err != nil { + panic(err) + } + stream.XORKeyStream(plaintext2, ciphertext[ivSize:]) + + fmt.Printf("%s\n", plaintext2) + // Output: some plaintext +} + +func ExampleNewCipher_zuc256() { + // Load your secret key from a safe place and reuse it across multiple + // NewCipher calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + key, _ := hex.DecodeString("6368616e6765207468697320706173736368616e676520746869732070617373") + plaintext := []byte("some plaintext") + + const ivSize = zuc.IVSize256 + // The IV needs to be unique, but not secure. Therefore it's common to + // include it at the beginning of the ciphertext. + ciphertext := make([]byte, ivSize+len(plaintext)) + iv := ciphertext[:ivSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + panic(err) + } + + stream, err := zuc.NewCipher(key, iv) + if err != nil { + panic(err) + } + stream.XORKeyStream(ciphertext[ivSize:], plaintext) + + // It's important to remember that ciphertexts must be authenticated + // (i.e. by using crypto/hmac) as well as being encrypted in order to + // be secure. + + // Stream cipher is the same for both encryption and decryption, so we can + // also decrypt that ciphertext with NewCTR. + + plaintext2 := make([]byte, len(plaintext)) + stream, err = zuc.NewCipher(key, iv) + if err != nil { + panic(err) + } + stream.XORKeyStream(plaintext2, ciphertext[ivSize:]) + + fmt.Printf("%s\n", plaintext2) + // Output: some plaintext +} + +func ExampleNewHash() { + // Load your secret key from a safe place and reuse it across multiple + // NewCipher calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + key, _ := hex.DecodeString("6368616e676520746869732070617373") + + // iv should be generated randomly + iv, _ := hex.DecodeString("6368616e676520746869732070617373") + + h, err := zuc.NewHash(key, iv) + if err != nil { + panic(err) + } + h.Write([]byte("hello world\n")) + fmt.Printf("%x", h.Sum(nil)) + // Output: c43cd26a +} + +func ExampleNewHash256_tagSize4() { + // Load your secret key from a safe place and reuse it across multiple + // NewCipher calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + key, _ := hex.DecodeString("6368616e6765207468697320706173736368616e676520746869732070617373") + + // iv should be generated randomly + iv, _ := hex.DecodeString("6368616e6765207468697320706173736368616e676520") + + h, err := zuc.NewHash256(key, iv, 4) + if err != nil { + panic(err) + } + h.Write([]byte("hello world\n")) + fmt.Printf("%x", h.Sum(nil)) + // Output: b76f96ed +}