github.com/emmansun/gmsm@v0.29.1/docs/zuc.md (about)

     1  # 祖冲之序列密码算法应用指南
     2  
     3  ## 参考标准
     4  * 《GB/T 33133.1-2016 信息安全技术 祖冲之序列密码算法 第1部分:算法描述》
     5  * 《GB/T 33133.2-2021 信息安全技术 祖冲之序列密码算法 第2部分:保密性算法》
     6  * 《GB/T 33133.3-2021 信息安全技术 祖冲之序列密码算法 第2部分:完整性算法》
     7  * [《祖冲之算法:ZUC-256算法草案(中文)》](https://github.com/guanzhi/GM-Standards/blob/master/%E5%85%AC%E5%BC%80%E6%96%87%E6%A1%A3/%E7%A5%96%E5%86%B2%E4%B9%8B%E7%AE%97%E6%B3%95%EF%BC%9AZUC-256%E7%AE%97%E6%B3%95%E8%8D%89%E6%A1%88(%E4%B8%AD%E6%96%87).pdf)
     8  
     9  您可以从[国家标准全文公开系统](https://openstd.samr.gov.cn/)在线阅读这些标准。
    10  
    11  ## 保密性算法
    12  保密性算法EEA实现了```cipher.Stream```接口,所以和其它流密码算法使用类似,只是创建方法不同而已。
    13  
    14  |  | ZUC-128 | ZUC-256 |  
    15  | :--- | :--- | :--- |
    16  | Key字节数 | 16 | 32 |
    17  | IV字节数 | 16 | 23 |  
    18  
    19  ```go
    20  func ExampleNewCipher() {
    21  	// Load your secret key from a safe place and reuse it across multiple
    22  	// NewCipher calls. (Obviously don't use this example key for anything
    23  	// real.) If you want to convert a passphrase to a key, use a suitable
    24  	// package like bcrypt or scrypt.
    25  	key, _ := hex.DecodeString("6368616e676520746869732070617373")
    26  	plaintext := []byte("some plaintext")
    27  
    28  	const ivSize = zuc.IVSize128
    29  	// The IV needs to be unique, but not secure. Therefore it's common to
    30  	// include it at the beginning of the ciphertext.
    31  	ciphertext := make([]byte, ivSize+len(plaintext))
    32  	iv := ciphertext[:ivSize]
    33  	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    34  		panic(err)
    35  	}
    36  
    37  	stream, err := zuc.NewCipher(key, iv)
    38  	if err != nil {
    39  		panic(err)
    40  	}
    41  	stream.XORKeyStream(ciphertext[ivSize:], plaintext)
    42  
    43  	// It's important to remember that ciphertexts must be authenticated
    44  	// (i.e. by using crypto/hmac) as well as being encrypted in order to
    45  	// be secure.
    46  
    47  	// Stream cipher is the same for both encryption and decryption, so we can
    48  	// also decrypt that ciphertext with NewCTR.
    49  
    50  	plaintext2 := make([]byte, len(plaintext))
    51  	stream, err = zuc.NewCipher(key, iv)
    52  	if err != nil {
    53  		panic(err)
    54  	}
    55  	stream.XORKeyStream(plaintext2, ciphertext[ivSize:])
    56  
    57  	fmt.Printf("%s\n", plaintext2)
    58  	// Output: some plaintext
    59  }
    60  
    61  func ExampleNewCipher_zuc256() {
    62  	// Load your secret key from a safe place and reuse it across multiple
    63  	// NewCipher calls. (Obviously don't use this example key for anything
    64  	// real.) If you want to convert a passphrase to a key, use a suitable
    65  	// package like bcrypt or scrypt.
    66  	key, _ := hex.DecodeString("6368616e6765207468697320706173736368616e676520746869732070617373")
    67  	plaintext := []byte("some plaintext")
    68  
    69  	const ivSize = zuc.IVSize256
    70  	// The IV needs to be unique, but not secure. Therefore it's common to
    71  	// include it at the beginning of the ciphertext.
    72  	ciphertext := make([]byte, ivSize+len(plaintext))
    73  	iv := ciphertext[:ivSize]
    74  	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    75  		panic(err)
    76  	}
    77  
    78  	stream, err := zuc.NewCipher(key, iv)
    79  	if err != nil {
    80  		panic(err)
    81  	}
    82  	stream.XORKeyStream(ciphertext[ivSize:], plaintext)
    83  
    84  	// It's important to remember that ciphertexts must be authenticated
    85  	// (i.e. by using crypto/hmac) as well as being encrypted in order to
    86  	// be secure.
    87  
    88  	// Stream cipher is the same for both encryption and decryption, so we can
    89  	// also decrypt that ciphertext with NewCTR.
    90  
    91  	plaintext2 := make([]byte, len(plaintext))
    92  	stream, err = zuc.NewCipher(key, iv)
    93  	if err != nil {
    94  		panic(err)
    95  	}
    96  	stream.XORKeyStream(plaintext2, ciphertext[ivSize:])
    97  
    98  	fmt.Printf("%s\n", plaintext2)
    99  	// Output: some plaintext
   100  }
   101  ```
   102  
   103  ## 完整性算法
   104  完整性算法实现了```hash.Hash```接口,所以其使用方法和其它哈希算法类似。
   105  
   106  |  | ZUC-128 | ZUC-256 |  
   107  | :--- | :--- | :--- |
   108  | Key字节数 | 16 | 32 |
   109  | IV字节数 | 16 | 23 | 
   110  | MAC字节数 | 4 | 4/8/16 | 
   111  
   112  ```go
   113  func ExampleNewHash() {
   114  	// Load your secret key from a safe place and reuse it across multiple
   115  	// NewCipher calls. (Obviously don't use this example key for anything
   116  	// real.) If you want to convert a passphrase to a key, use a suitable
   117  	// package like bcrypt or scrypt.
   118  	key, _ := hex.DecodeString("6368616e676520746869732070617373")
   119  
   120  	// iv should be generated randomly
   121  	iv, _ := hex.DecodeString("6368616e676520746869732070617373")
   122  
   123  	h, err := zuc.NewHash(key, iv)
   124  	if err != nil {
   125  		panic(err)
   126  	}
   127  	h.Write([]byte("hello world\n"))
   128  	fmt.Printf("%x", h.Sum(nil))
   129  	// Output: c43cd26a
   130  }
   131  
   132  func ExampleNewHash256_tagSize4() {
   133  	// Load your secret key from a safe place and reuse it across multiple
   134  	// NewCipher calls. (Obviously don't use this example key for anything
   135  	// real.) If you want to convert a passphrase to a key, use a suitable
   136  	// package like bcrypt or scrypt.
   137  	key, _ := hex.DecodeString("6368616e6765207468697320706173736368616e676520746869732070617373")
   138  
   139  	// iv should be generated randomly
   140  	iv, _ := hex.DecodeString("6368616e6765207468697320706173736368616e676520")
   141  
   142  	h, err := zuc.NewHash256(key, iv, 4)
   143  	if err != nil {
   144  		panic(err)
   145  	}
   146  	h.Write([]byte("hello world\n"))
   147  	fmt.Printf("%x", h.Sum(nil))
   148  	// Output: b76f96ed
   149  }
   150  
   151  func ExampleNewHash256_tagSize8() {
   152  	// Load your secret key from a safe place and reuse it across multiple
   153  	// NewCipher calls. (Obviously don't use this example key for anything
   154  	// real.) If you want to convert a passphrase to a key, use a suitable
   155  	// package like bcrypt or scrypt.
   156  	key, _ := hex.DecodeString("6368616e6765207468697320706173736368616e676520746869732070617373")
   157  
   158  	// iv should be generated randomly
   159  	iv, _ := hex.DecodeString("6368616e6765207468697320706173736368616e676520")
   160  
   161  	h, err := zuc.NewHash256(key, iv, 8)
   162  	if err != nil {
   163  		panic(err)
   164  	}
   165  	h.Write([]byte("hello world\n"))
   166  	fmt.Printf("%x", h.Sum(nil))
   167  	// Output: f28aea6c9db3dc69
   168  }
   169  
   170  func ExampleNewHash256_tagSize16() {
   171  	// Load your secret key from a safe place and reuse it across multiple
   172  	// NewCipher calls. (Obviously don't use this example key for anything
   173  	// real.) If you want to convert a passphrase to a key, use a suitable
   174  	// package like bcrypt or scrypt.
   175  	key, _ := hex.DecodeString("6368616e6765207468697320706173736368616e676520746869732070617373")
   176  
   177  	// iv should be generated randomly
   178  	iv, _ := hex.DecodeString("6368616e6765207468697320706173736368616e676520")
   179  
   180  	h, err := zuc.NewHash256(key, iv, 16)
   181  	if err != nil {
   182  		panic(err)
   183  	}
   184  	h.Write([]byte("hello world\n"))
   185  	fmt.Printf("%x", h.Sum(nil))
   186  	// Output: fd8d10ea65b6369cccc07d50b4657d84
   187  }
   188  ```
   189  
   190  要支持位为单位的话,可以调用```Finish```方法。
   191  ```go
   192  func ExampleZUC128Mac_Finish() {
   193  	key := make([]byte, 16)
   194  	iv := make([]byte, 16)
   195  	h, err := zuc.NewHash(key, iv)
   196  	if err != nil {
   197  		panic(err)
   198  	}
   199  	fmt.Printf("%x", h.Finish([]byte{0}, 1))
   200  	// Output: c8a9595e
   201  }
   202  
   203  func ExampleZUC128Mac_Finish_mixed() {
   204  	key := []byte{
   205  		0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
   206  		0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a,
   207  	}
   208  
   209  	// iv should be generated randomly
   210  	iv, _ := hex.DecodeString("a94059da50000000294059da50008000")
   211  
   212  	h, err := zuc.NewHash(key, iv)
   213  	if err != nil {
   214  		panic(err)
   215  	}
   216  
   217  	in, _ := hex.DecodeString("983b41d47d780c9e1ad11d7eb70391b1de0b35da2dc62f83e7b78d6306ca0ea07e941b7be91348f9fcb170e2217fecd97f9f68adb16e5d7d21e569d280ed775cebde3f4093c53881")
   218  	h.Write(in)
   219  	fmt.Printf("%x", h.Finish([]byte{0}, 1))
   220  	// Output: fae8ff0b
   221  }
   222  ```