# Method of using encryption algorithm in go

Time：2021-10-15

## Hash algorithm

`md5`

128bit, 16 bytes

For example: MD5 (“Hello world!”) = fc3ff98e8c6a0d3087d515c0473f8677 / / 32-bit hexadecimal digit

?
 1 2 3 4 5 6 7 8 9 10 11 12 13 `func Test(t *testing.T) {` `    ``//Method 1` `    ``str := "hello world!"` `    ``has := md5.Sum([]byte(str))` `    ``Md5str1: = FMT. Sprintf ('% X', has) // convert [] byte to hexadecimal` `    ``t.Log(md5str1)`   `    ``//Method 2` `    ``w := md5.New()` `    ``io.WriteString(w, str)` `    ``md5str2 := fmt.Sprintf("%x", w.Sum(nil))` `    ``t.Log(md5str2)` `}`

SHA1

160bit, 20 bytes

For example: SHA1 (“Hello world!”) = 430ce34d020724ed75a196dfc2ad67c7772d169 / / 40 hexadecimal digits

?
 1 2 3 4 5 6 7 8 9 10 11 12 `func Test(t *testing.T) {` `    ``str := "hello world!"`   `    ``//The method of generating a hash value is SHA1. New(), SHA1. Write (bytes), and then SHA1. Sum ([] byte {}).` `    ``h := sha1.New()`   `    ``//Write the bytes to be processed.` `    ``h.Write([]byte(str))`   `    ``//SHA1 values are often output in hexadecimal, such as in Git commit.` `    ``t.Log(hex.EncodeToString(h.Sum(nil)))` `}`

RIPEMD-160

160bit, 20 bytes

For example: ripemd-160 (“Hello world!”) = dffd03137b3a333d5754813399a5f437acd694e5 / / 40 hexadecimal digits

?
 1 2 3 4 5 6 7 `func Test(t *testing.T) {` `    ``str := "hello world!"`   `    ``h := ripemd160.New()` `    ``h.Write([]byte(str))` `    ``t.Log(hex.EncodeToString(h.Sum(nil)))` `}`

SHA256

256bit, 32 bytes

For example: sha256 (“Hello world!”) = 7509e5bda0c762d2bac7f90d758b5b2263fa01ccb542ab5e3df163be08e6ca9 / / 64 bit hexadecimal digit

?
 1 2 3 4 5 6 7 8 9 10 11 12 `func Test(t *testing.T) {` `    ``str := "hello world!"`   `    ``//First call method` `    ``sum := sha256.Sum256([]byte(str))` `    ``t.Logf("%x\n", sum)`   `    ``//The second calling method` `    ``h := sha256.New()` `    ``io.WriteString(h,str)` `    ``t.Log(hex.EncodeToString(h.Sum(nil)))` `}`

Implementation principle of sha256
The maximum length of the input message of SHA-256 algorithm is no more than 2 ^ 64 bits. The input message is grouped by 512 bits and processed. The output of the output message is a 256 bit message summary.
Sha256 algorithm includes the following steps:

The message is filled in so that the message degree is congruent with 448 modulo 512 (⻓ degree = 448 mod512). The filled ⽐ special number range is 1 to 512. The most ⾼ bit of the filled ⽐ special string is 1 and the other bits are 0. That is, first add a 1 after reporting ⽂ and then add many zeros until ⻓ degree is full ⾜ mod512 = 448. Why 448? 448 + 64 = 512. In step ⼆ the degree information of ⼀ 64bit original message ⽂ will be added. Additional ⻓ degree value
Attach the bit degree of the initial message ⽂ (before filling) represented by ⽤ 64 bit to the result of step 1 (low byte priority) to initialize the cache
Make a 256 bit cache to store the intermediate and final results of the hash function. The cache is represented as:
A=0x6A09E667
B=0xBB67AE85
C=0x3C6EF372
D=0xA54FF53A
E=0x510E527F
F=0x9B05688C
G=0x1F83D9AB
H = 0x5be0cd19 processing 512bit (16 words) message ⽂ packet sequence
The algorithm makes ⽤ six basic logic functions, which are composed of 64 step iterative operations. Each step takes 256 bit cache abcdefgh as the input, and then updates the cache content. Make ⽤ 32bit constant values KT and ⼀ 32bit WT in each step.

SHA512

512bit, 64 bytes

For example: SHA512 (“Hello world!”) = db9b1cd3262dee37756a09b9064973589847caa8e53d31a9d142ea2701b1b28abd97838bb9a27068ba305dc8d04a45a1fcf079de54d607666996b3cc54f6b67c / / 128 hexadecimal digits

?
 1 2 3 4 5 6 7 8 9 10 11 12 `func Test(t *testing.T) {` `    ``str := "hello world!"`   `    ``//First call method` `    ``sum := sha512.Sum512([]byte(str))` `    ``t.Logf("%x\n", sum)`   `    ``//The second calling method` `    ``h := sha512.New()` `    ``io.WriteString(h,str)` `    ``t.Log(hex.EncodeToString(h.Sum(nil)))` `}`

## Encryption mode

Encryption is generally divided into symmetric key encryption and asymmetric key encryption.

Symmetric encryption is divided into block encryption and sequence cipher.

Block ciphers, also known as block ciphers, encrypt one block in plaintext at a time. Plaintext is grouped according to a certain bit length. The plaintext group is encrypted to obtain the ciphertext group. The ciphertext group is restored to the plaintext group after decryption operation (inverse operation of encryption operation).

Sequence ciphers, also known as stream ciphers, encrypt one bit in plaintext at a time. It refers to the use of a small number of keys (scrambling elements) to generate a large number of pseudo-random bit streams through some complex operation (cryptographic algorithm) for the encryption of plaintext bit streams.

Decryption refers to using the same key and cryptographic algorithm and the same pseudo-random bit stream as encryption to restore the plaintext bit stream.

In the block encryption algorithm, there are several algorithm modes: ECB, CBC, CFB and OFB.

Encryption mode explain
ECB The most basic encryption mode, which is commonly understood as encryption, will always be encrypted into the same secret and initial vector. It is vulnerable to codebook replay attacks. In general, it is rare
CBC It is clear that before being encrypted, it is necessary to carry out exclusive or operation with the secret of the previous one and then encrypt it. Therefore, as long as different initial vectors are selected, the same secret will form different secret after encryption, which is the most extensive mode of the previous one. The secret ⽂ after CBC encryption is related to the upper and lower ⽂ but the error of ⽂ will not be transmitted to the subsequent packets, but if ⼀ packets are lost, all the subsequent ⾯ packets will be invalidated (synchronization error)
CFB Similar to ⾃ synchronous sequence cipher, after block encryption, shift the secret and explicit into ⾏ XOR according to 8-bit grouping to obtain the output, and feed back to the shift register at the same time. The advantages are that ⼩ can be encrypted and decrypted by byte or N bits. CFB is also up and down related. In CFB mode, ⽂ errors of explicit will affect the secret (error diffusion) of subsequent ⾯.
OFB The block cipher is operated as a synchronous sequence cipher, which is similar to CFB, but OFB is the first n-bit cipher, and the output packet is fed back to the shift register. OFB has no error diffusion problem

## Symmetric encryption

The most commonly used symmetric encryption algorithms are des, 3DES (tripledes) and AES. The filling ⽅ formulas commonly used are nopadding (no filling), zeros filling (0 filling) and pkcs5padding filling.

The encryption algorithm requires plaintext to be aligned according to a certain length, which is called block size. For example, 8 bytes. For an arbitrary piece of data, the last block needs to be filled to 8 bytes before encryption, and the filled data needs to be deleted after decryption.

Filled ⽅ type explain
ZeroPadding When the data length is not uniform, use 0 to fill, otherwise do not fill
PKCS7Padding Assuming that the data length needs to be filled with n (n > 0) bytes before alignment, fill n bytes, and each byte is n; If the data itself is already aligned, a block of data with a length of block size is filled, and each byte is block size
PKCS5Padding A subset of pkcs7padding with a fixed block size of 8 bytes

Since the last byte must be the length of the filled data when pkcs7padding / pkcs5padding is used, the filled data can be accurately deleted after decryption. When zeropadding is used, there is no way to distinguish between real data and filled data, so it is only suitable for encryption and decryption of strings ending with \ 0.

Filling function required for symmetric encryption

?
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 `func PKCS5Padding(data []byte, blockSize int) []byte {` `    ``padding := blockSize - len(data)%blockSize` `    ``padtext := bytes.Repeat([]byte{byte(padding)}, padding)` `    ``return append(data, padtext...)` `}`   `func PKCS5UnPadding(data []byte) []byte {` `    ``length := len(data)` `    ``//Remove the last byte unpadding times` `    ``unpadding := int(data[length-1])` `    ``return data[:(length - unpadding)]` `}`   `func ZeroPadding(data []byte, blockSize int) []byte {` `    ``padding := blockSize - len(data)%blockSize` `    ``padtext := bytes.Repeat([]byte{0}, padding)` `    ``return append(data, padtext...)` `}`   `func ZeroUnPadding(data []byte) []byte {` `    ``return bytes.TrimRightFunc(data, func(r rune) bool {` `        ``return r == rune(0)` `    ``})` `}`

DES

?
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 `//Des encrypts byte array and returns byte array` `func DesEncrypt(originalBytes, key []byte) ([]byte, error) {` `    ``block, err := des.NewCipher(key)` `    ``if err != nil {` `        ``return nil, err` `    ``}` `    ``originalBytes = PKCS5Padding(originalBytes, block.BlockSize())` `    ``blockMode := cipher.NewCBCEncrypter(block, key)` `    ``cipherArr := make([]byte, len(originalBytes))` `    ``blockMode.CryptBlocks(cipherArr, originalBytes)` `    ``return cipherArr, nil` `}`   `//Des decrypts the byte array and returns the byte array` `func DesDecrypt(cipherBytes, key []byte) ([]byte, error) {` `    ``block, err := des.NewCipher(key)` `    ``if err != nil {` `        ``return nil, err` `    ``}` `    ``blockMode := cipher.NewCBCDecrypter(block, key)` `    ``originalText := make([]byte, len(cipherBytes))` `    ``blockMode.CryptBlocks(originalText, cipherBytes)` `    ``originalText = PKCS5UnPadding(originalText)` `    ``return originalText, nil` `}`   `//Des encrypted ⽂ book, return the encrypted ⽂ book` `func DesEncryptString(originalText string, key []byte) (string, error) {` `    ``cipherArr, err := DesEncrypt([]byte(originalText), key)` `    ``if err != nil {` `        ``return "", err` `    ``}` `    ``base64str := base64.StdEncoding.EncodeToString(cipherArr)` `    ``return base64str, nil` `}`   `//Decrypt the encrypted ⽂ text into ⾏ DES, and return the decrypted ⽂` `func DesDecryptString(cipherText string, key []byte) (string, error) {` `    ``cipherArr, _ := base64.StdEncoding.DecodeString(cipherText)` `    ``cipherArr, err := DesDecrypt(cipherArr, key)` `    ``if err != nil {` `        ``return "", err` `    ``}` `    ``return string(cipherArr), nil` `}`

3DES

?
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 `//3DES encrypts byte array and returns byte array` `func TripleDesEncrypt(originalBytes, key []byte) ([]byte, error) {` `    ``block, err := des.NewTripleDESCipher(key)` `    ``if err != nil {` `        ``return nil, err` `    ``}` `    ``originalBytes = PKCS5Padding(originalBytes, block.BlockSize())` `    ``// originalBytes = ZeroPadding(originalBytes, block.BlockSize())` `    ``blockMode := cipher.NewCBCEncrypter(block, key[:8])` `    ``cipherArr := make([]byte, len(originalBytes))` `    ``blockMode.CryptBlocks(cipherArr, originalBytes)` `    ``return cipherArr, nil` `}`   `//3DES decrypts the byte array and returns the byte array` `func TripleDesDecrypt(cipherBytes, key []byte) ([]byte, error) {` `    ``block, err := des.NewTripleDESCipher(key)` `    ``if err != nil {` `        ``return nil, err` `    ``}` `    ``blockMode := cipher.NewCBCDecrypter(block, key[:8])` `    ``originalArr := make([]byte, len(cipherBytes))` `    ``blockMode.CryptBlocks(originalArr, cipherBytes)` `    ``originalArr = PKCS5UnPadding(originalArr)` `    ``// origData = ZeroUnPadding(origData)` `    ``return originalArr, nil` `}`   `//3DES encrypts the string and returns the string after Base64 processing` `func TripleDesEncrypt2Str(originalText string, key []byte) (string, error) {` `    ``block, err := des.NewTripleDESCipher(key)` `    ``if err != nil {` `        ``return "", err` `    ``}` `    ``originalData := PKCS5Padding([]byte(originalText), block.BlockSize())` `    ``// originalData = ZeroPadding(originalData, block.BlockSize())` `    ``blockMode := cipher.NewCBCEncrypter(block, key[:8])` `    ``cipherArr := make([]byte, len(originalData))` `    ``blockMode.CryptBlocks(cipherArr, originalData)` `    ``cipherText := base64.StdEncoding.EncodeToString(cipherArr)` `    ``return cipherText, nil` `}`   `//3DES decrypts the encrypted string processed by Base64 and returns the explicit string` `func TripleDesDecrypt2Str(cipherText string, key []byte) (string, error) {` `    ``cipherArr, _ := base64.StdEncoding.DecodeString(cipherText)` `    ``block, err := des.NewTripleDESCipher(key)` `    ``if err != nil {` `        ``return "", err` `    ``}` `    ``blockMode := cipher.NewCBCDecrypter(block, key[:8])` `    ``originalArr := make([]byte, len(cipherArr))` `    ``blockMode.CryptBlocks(originalArr, cipherArr)` `    ``originalArr = PKCS5UnPadding(originalArr)` `    ``// origData = ZeroUnPadding(origData)` `    ``return string(originalArr), nil` `}`

AES

?
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 `//AES encrypts byte array and returns byte array` `func AesEncrypt(originalBytes, key []byte) ([]byte, error) {` `    ``block, err := aes.NewCipher(key)` `    ``if err != nil {` `        ``return nil, err` `    ``}` `    ``blockSize := block.BlockSize()` `    ``originalBytes = PKCS5Padding(originalBytes, blockSize)` `    ``// originalBytes = ZeroPadding(originalBytes, block.BlockSize())` `    ``blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])` `    ``cipherBytes := make([]byte, len(originalBytes))` `    ``//According to the description of cryptblocks ⽅ method, the following ⽅ formula can also initialize crypted` `    ``// crypted := originalBytes` `    ``blockMode.CryptBlocks(cipherBytes, originalBytes)` `    ``return cipherBytes, nil` `}`   `//AES decrypts the byte array and returns the byte array` `func AesDecrypt(cipherBytes, key []byte) ([]byte, error) {` `    ``block, err := aes.NewCipher(key)` `    ``if err != nil {` `        ``return nil, err` `    ``}` `    ``blockSize := block.BlockSize()` `    ``blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])` `    ``originalBytes := make([]byte, len(cipherBytes))` `    ``// origData := cipherBytes` `    ``blockMode.CryptBlocks(originalBytes, cipherBytes)` `    ``originalBytes = PKCS5UnPadding(originalBytes)` `    ``// origData = ZeroUnPadding(origData)` `    ``return originalBytes, nil` `}`   `//AES encryption ⽂ book returns the string after ⾏ Base64 processing of the encrypted byte array` `func AesEncryptString(originalText string, key []byte) (string, error) {` `    ``cipherBytes, err := AesEncrypt([]byte(originalText), key)` `    ``if err != nil {` `        ``return "", err` `    ``}` `    ``base64str := base64.StdEncoding.EncodeToString(cipherBytes)` `    ``return base64str, nil` `}`   `//AES decryption ⽂ book, enter ⾏ AES decryption for the encrypted ⽂ Book processed by Base64, and return the decrypted ⽂` `func AesDecryptString(cipherText string, key []byte) (string, error) {` `    ``cipherBytes, _ := base64.StdEncoding.DecodeString(cipherText)` `    ``cipherBytes, err := AesDecrypt(cipherBytes, key)` `    ``if err != nil {` `        ``return "", err` `    ``}` `    ``return string(cipherBytes), nil` `}`

## ⾮ symmetric encryption

RSA algorithm is also a block cipher algorithm, which always operates on a fixed length block. However, unlike AES, block length is related to key length.

The length of plaintext encrypted by RSA each time is limited by RSA filling mode, but the block length encrypted by RSA each time is key length.

Filled ⽅ type Ciphertext length
PKCS1Padding It must be at least 11 bytes shorter than the RSA secret key module, that is, RSA_ SIZE(rsa) – 11
NOPadding It can be as long as the RSA key module. If the input plaintext is too long, it must be cut and filled

In different padding modes, the maximum length of data that can be encrypted with the same length of key is different. In different key lengths, the maximum length of data that can be encrypted with the same padding mode is also different

Therefore, it is not rigorous to discuss the maximum length that the padding mode can encrypt without the key length. The commonly used key lengths are 1024 bits, 2048 bits, etc. theoretically, the maximum length of data that can be encrypted by the 1024 bits key is 1024 bits (i.e. 1024 / 8 = 128bytes). The maximum length of data that can be encrypted by the key of 2048 bits is 2048 bits (2048 / 8 = 256 bytes), but RSA cannot use this “textbook RSA” system in practical application. In practical applications, RSA is often used together with padding technology, which can increase the security of RSA.

PKCS1

?
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 `//Encrypt byte array and return byte array` `func RsaEncrypt(publicKey, origData []byte) ([]byte, error) {` `    ``block, _ := pem.Decode(publicKey)` `    ``if block == nil {` `        ``return nil, errors.New("public key error")` `    ``}` `    ``pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)` `    ``if err != nil {` `        ``return nil, err` `    ``}` `    ``pub := pubInterface.(*rsa.PublicKey)` `    ``return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)` `}`   `//Decrypt byte array and return byte array` `func RsaDecrypt(privateKey, ciphertext []byte) ([]byte, error) {` `    ``block, _ := pem.Decode(privateKey)` `    ``if block == nil {` `        ``return nil, errors.New("private key error!")` `    ``}` `    ``priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)` `    ``if err != nil {` `        ``return nil, err` `    ``}` `    ``return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)` `}`   `//Encrypts the string and returns the string processed by Base64` `func RsaEncryptString(publicKey []byte, origData string) (string, error) {` `    ``block, _ := pem.Decode(publicKey)` `    ``if block == nil {` `        ``return "", errors.New("public key error")` `    ``}` `    ``pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)` `    ``if err != nil {` `        ``return "", err` `    ``}` `    ``pub := pubInterface.(*rsa.PublicKey)` `    ``cipherArr, err := rsa.EncryptPKCS1v15(rand.Reader, pub, []byte(origData))` `    ``if err != nil {` `        ``return "", err` `    ``} else {` `        ``return base64.StdEncoding.EncodeToString(cipherArr), nil` `    ``}` `}`   `//Decrypt the encrypted string processed by Base64 and return the information before encryption` `func RsaDecryptString(privateKey []byte, cipherText string) (string, error) {` `    ``block, _ := pem.Decode(privateKey)` `    ``if block == nil {` `        ``return "", errors.New("private key error!")` `    ``}` `    ``priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)` `    ``if err != nil {` `        ``return "", err` `    ``}` `    ``cipherArr, _ := base64.StdEncoding.DecodeString(cipherText)` `    ``originalArr, err := rsa.DecryptPKCS1v15(rand.Reader, priv, cipherArr)` `    ``if err != nil {` `        ``return "", err` `    ``} else {` `        ``return string(originalArr), nil` `    ``}` `}`

OAEP

?
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 `//Encryption` `func EncryptOAEP(publicKey []byte, text string) (string, error) {` `    ``block, _ := pem.Decode(publicKey)` `    ``if block == nil {` `        ``return "", errors.New("public key error")` `    ``}`   `    ``pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)` `    ``if err != nil {` `        ``return "", err` `    ``}`   `    ``pub := pubInterface.(*rsa.PublicKey)`   `    ``secretMessage := []byte(text)` `    ``rng := rand.Reader` `    ``cipherdata, err := rsa.EncryptOAEP(sha1.New(), rng, pub, secretMessage, nil)` `    ``if err != nil {` `        ``return "", err` `    ``}` `    ``ciphertext := base64.StdEncoding.EncodeToString(cipherdata)` `    ``return ciphertext, nil` `}`   `//Decryption` `func DecryptOAEP(privateKey []byte, ciphertext string) (string, error) {` `    ``block, _ := pem.Decode(privateKey)` `    ``if block == nil {` `        ``return "", errors.New("private key error!")` `    ``}`   `    ``priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)` `    ``if err != nil {` `        ``return "", err` `    ``}`   `    ``cipherdata, _ := base64.StdEncoding.DecodeString(ciphertext)` `    ``rng := rand.Reader` `    ``plaintext, err := rsa.DecryptOAEP(sha1.New(), rng, priv, cipherdata, nil)` `    ``if err != nil {` `        ``return "", err` `    ``}` `    ``return string(plaintext), nil` `}`

## Elliptic curve encryption algorithm ECC

Elliptic curve cryptography (ECC) is a symmetric encryption algorithm based on the mathematical theory of elliptic curve.

Advantages of ECC and RSA algorithms

Elliptic curve public key system is a strong competitor to replace RSA.

Compared with the classical RSA, DSA and other public key cryptosystems, the elliptic cryptosystem has the following advantages:

(1) Better security performance (ECC can make ⽤ shorter keys):

The security strength of 160 bit ECC encryption algorithm is equivalent to 1024 bit RSA encryption;

The security strength of 210 bit ECC encryption algorithm is equivalent to 2048 bit RSA encryption.

(2) Fast processing speed: the amount of calculation and processing speed are fast. In terms of the processing speed of the private key (decryption and signature), ECC is much faster than RSA and DSA.

(3) Storage space occupation: ECC’s key ruler and system parameters are much more similar to RSA and DSA, so it occupies much more storage space.

(4) Low bandwidth requirements make ECC have broad application prospects. Because of these characteristics, ECC will replace RSA and become a common public key encryption algorithm.

?
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 `//Generate ECC elliptic curve key pair` `func GenerateECCKey() (*ecdsa.PublicKey, *ecdsa.PrivateKey, error) {` `    ``privateKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)` `    ``if err != nil {` `        ``return nil, nil, err` `    ``}`   `    ``publicKey := &privateKey.PublicKey` `    ``return publicKey, privateKey, nil` `}`   `//Generate a digital signature on the hash value of the message` `func SignECC(msg []byte) ([]byte, []byte) {` `    ``//Get private key` `    ``_, privateKey, err := GenerateECCKey()` `    ``if err != nil {` `        ``panic(err)` `    ``}`   `    ``//Calculate hash value` `    ``hash := sha256.New()`   `    ``//Fill in data` `    ``hash.Write(msg)` `    ``b := hash.Sum(nil)`   `    ``//Generate a digital signature on the hash value` `    ``r, s, err := ecdsa.Sign(rand.Reader, privateKey, b)` `    ``if err != nil {` `        ``panic(err)` `    ``}`   `    ``rtext, _ := r.MarshalText()` `    ``stext, _ := s.MarshalText()` `    ``return rtext, stext` `}`   `//Verify digital signature` `func VerifySignECC(msg []byte, rtext, stext []byte) bool {` `    ``//Get public key` `    ``publicKey, _, err := GenerateECCKey()` `    ``if err != nil {` `        ``panic(err)` `    ``}`   `    ``//Calculate hash value` `    ``hash := sha256.New()` `    ``hash.Write(msg)` `    ``b := hash.Sum(nil)`   `    ``//Verify digital signature` `    ``var r, s big.Int` `    ``if err := r.UnmarshalText(rtext); err != nil {` `        ``panic(err)` `    ``}` `    ``if err := s.UnmarshalText(stext); err != nil {` `        ``panic(err)` `    ``}`   `    ``verify := ecdsa.Verify(publicKey, b, &r, &s)` `    ``return verify` `}`   `//Testing` `func Test(t *testing.T) {` `    ``//Analog sender` `    ``//Message to send` `    ``msg := []byte("hello world")` `    ``//Generate digital signature` `    ``rtext, stext := SignECC(msg)`   `    ``//Simulated recipient` `    ``//Received message` `    ``acceptmsg := []byte("hello world")` `    ``//Received signature` `    ``acceptrtext := rtext` `    ``acceptstext := stext` `    ``//Verify signature` `    ``verifySignECC := VerifySignECC(acceptmsg, acceptrtext, acceptstext)` `    ``FMT. Println ("verification result:", verifysignecc)` `}`

## digital signature

Concept of digital signature

1. Signature unforgeability;
2. The signature is undeniable;
3. Signature credibility, signature recognition and response are relatively easy, and any (can verify the validity of the signature
Sex;
4. Signature cannot be copied, and signature and original ⽂ are an inseparable whole;
5. The signature message cannot be tampered with because any special data is tampered with, and its signature will be changed accordingly
Any x (verifiable ⽽ refuses to accept this signature.

Elliptic curve digital signature algorithm ECDSA

?
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 `//⽣ generate a private key and a public key, and the generated private key is the pointer of the structure ecdsa.privatekey` `func NewKeyPair() (ecdsa.PrivateKey, []byte) {` `    ``//⽣ form secp256 elliptic curve` `    ``curve := elliptic.P256()` `    ``//Generated are structure pointers, and the structure type is ecdsa.privatekey` `    ``private, err := ecdsa.GenerateKey(curve, rand.Reader)` `    ``if err != nil {` `        ``log.Panic(err)` `    ``}` `    ``FMT. Printf ("private key:% X \ n", private)` `    ``FMT. Printf ("private key X:% X \ n", private. X.bytes())` `    ``FMT. Printf ("private key Y:% X \ n", private. Y. bytes())` `    ``FMT. Printf ("private key D:% X \ n", private. D. bytes())` `    ``//The X coordinate and Y coordinate are spliced from ⼀ to form a public key` `    ``pubKey := append(private.X.Bytes(), private.Y.Bytes()...)` `    ``//Print the public key. The public key ⽤ is printed in hexadecimal. The degree is 128, including X-axis coordinates and y-axis coordinates.` `    ``FMT. Printf ("public key:% X \ n", pubkey)` `    ``return *private, pubKey` `}`   `//⽣ der format of signature` `func MakeSignatureDerString(r, s string) string {` `    ``//Obtain the ⻓ degree of R and s` `    ``lenSigR := len(r) / 2` `    ``lenSigS := len(s) / 2` `    ``//Calculate the total ⻓ degree of Der sequence` `    ``lenSequence := lenSigR + lenSigS + 4` `    ``//Convert decimal ⻓ degrees to hexadecimal string` `    ``strLenSigR := DecimalToHex(int64(lenSigR))` `    ``strLenSigS := DecimalToHex(int64(lenSigS))` `    ``strLenSequence := DecimalToHex(int64(lenSequence))` `    ``//Pieced der code` `    ``derString := "30" + strLenSequence` `    ``derString = derString + "02" + strLenSigR + r` `    ``derString = derString + "02" + strLenSigS + s` `    ``derString = derString + "01"` `    ``return derString` `}`   `func DecimalToHex(n int64) string {` `    ``if n < 0 {` `        ``log.Println("Decimal to hexadecimal error: the argument must be greater than zero.")` `        ``return ""` `    ``}` `    ``if n == 0 {` `        ``return "0"` `    ``}`   `    ``hex := map[int64]int64{10: 65, 11: 66, 12: 67, 13: 68, 14: 69, 15: 70}` `    ``s := ""` `    ``for q := n; q > 0; q = q / 16 {` `        ``m := q % 16` `        ``if m > 9 && m < 16 {` `            ``m = hex[m]` `            ``s = fmt.Sprintf("%v%v", string(m), s)` `            ``continue` `        ``}` `        ``s = fmt.Sprintf("%v%v", m, s)` `    ``}` `    ``return s` `}`   `//Verify signature 1` `func VerifySig(pubKey, message []byte, r, s *big.Int) bool {` `    ``curve := elliptic.P256()` `    ``//Degree of public key` `    ``keyLen := len(pubKey)` `    ``//The front ⼀ half is X-axis coordinate and the rear ⼀ half is Y-axis coordinate` `    ``x := big.Int{}` `    ``y := big.Int{}` `    ``x.SetBytes(pubKey[:(keyLen / 2)])` `    ``y.SetBytes(pubKey[(keyLen / 2):])` `    ``rawPubKey := ecdsa.PublicKey{curve, &x, &y}` `    ``//The verification is successful according to the transaction hash, public key and digital signature. ecdsa.Verify func Verify(pub *PublicKey, hash[] byte, r * big.Int, s * big.Int) bool` `    ``res := ecdsa.Verify(&rawPubKey, message, r, s)` `    ``return res` `}`   `//Verify signature 2` `func VerifySignature(pubKey, message []byte, r, s string) bool {` `    ``curve := elliptic.P256()` `    ``//Degree of public key` `    ``keyLen := len(pubKey)` `    ``//The front ⼀ half is X-axis coordinate and the rear ⼀ half is Y-axis coordinate` `    ``x := big.Int{}` `    ``y := big.Int{}` `    ``x.SetBytes(pubKey[:(keyLen / 2)])` `    ``y.SetBytes(pubKey[(keyLen / 2):])` `    ``rawPubKey := ecdsa.PublicKey{curve, &x, &y}` `    ``//The verification is successful according to the transaction hash, public key and digital signature. ecdsa.Verify func Verify(pub *PublicKey, hash[] byte, r * big.Int, s * big.Int) bool` `    ``rint := big.Int{}` `    ``sint := big.Int{}` `    ``rByte, _ := hex.DecodeString(r)` `    ``sByte, _ := hex.DecodeString(s)` `    ``rint.SetBytes(rByte)` `    ``sint.SetBytes(sByte)` `    ``//fmt.Println("------", rint.SetBytes(rByte))` `    ``//fmt.Println("------", sint.SetBytes(sByte))` `    ``res := ecdsa.Verify(&rawPubKey, message, &rint, &sint)` `    ``return res` `}`   `//Verification process` `func Test(t *testing.T) {` `    ``//1. ⽣ signature` `    ``FMT. Println ("1. Signature -------------------------------")` `    ``//Call function to private key and public key` `    ``privKey, pubKey := NewKeyPair()` `    ``//Hash of information` `    ``msg := sha256.Sum256([]byte("hello world"))` `    ``//Enter the digital signature according to the hash of the private key and information, and produce ⽣ R and s` `    ``r, s, _ := ecdsa.Sign(rand.Reader, &privKey, msg[:])` `    ``//⽣ into R and s strings` `    ``fmt.Println("-------------------------------")` `    ``strSigR := fmt.Sprintf("%x", r)` `    ``strSigS := fmt.Sprintf("%x", s)` `    ``FMT. Println ("the decimal digits of R and s are:", R, s respectively)` `    ``FMT. Println ("hexadecimal of R and s are:", strsigr, strsigs respectively)` `    ``//R and s are spliced together to form the der format of digital signature` `    ``signatureDer := MakeSignatureDerString(strSigR, strSigS)` `    ``//Print hexadecimal display of digital signature` `    ``FMT. Println ("digital signature der format is:", signatureder)` `    ``fmt.Println()` `    ``//2. Signature verification process` `    ``FMT. Println ("2. Signature verification process -------------------------")` `    ``res := VerifySig(pubKey, msg[:], r, s)` `    ``FMT. Println ("signature verification result:", RES)` `    ``res = VerifySignature(pubKey, msg[:], strSigR, strSigS)` `    ``FMT. Println ("signature verification result:", RES)` `}`

## Character encoding / decoding

Base64

Base64 is a method of representing binary data based on 64 printable characters. Base64 enables 26 words, 26 words, 10 numbers and two symbols (such as “+” and “/”) to transmit binary data in a book based medium such as e-mail.

Base64 character set:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

To Base64

Convert each character into ASCII code (hexadecimal) convert the hexadecimal code into binary code divide the binary code according to the 6-bit ⼀ group ⾏ zero the binary number ⾼ bit of the 6-bit ⼀ group, and then convert it into hexadecimal number. Take the hexadecimal number as the index to find the character from the base64 coding table. The ⽂ book of every 3 characters will be encoded into 4 characters ⻓ degrees (3)8=46）
a. If ⽂ is 3 characters, it is exactly encoded as 4 characters ⻓ degrees;
b. If ⽂ this is 2 characters, it will be encoded as 3 characters. Since ⾜ 4 characters are not included, there will be ⽤ “=” at the end;
c. If ⽂ this is 1 character, it will be encoded as 2 characters. Since ⾜ 4 characters are not included, two “=” will be supplemented at the end.

## Shoulders Of Giants

Learn from the work of others to avoid repeating our mistakes, just as we can make better achievements by standing on the shoulders of giants.

https://github.com/rubyhan1314/Golang-100-Days
https://blog.csdn.net/luckydog612/article/details/80547758
https://www.cnblogs.com/yanzi-meng/p/9640578.html
https://www.cnblogs.com/starwolf/p/3365834.html
https://blog.csdn.net/u013073067/article/details/87086562
https://www.cnblogs.com/Terry-Wu/p/10314315.html
http://blog.studygolang.com/2013/01/go%E5%8A%A0%E5%AF%86%E8%A7%A3%E5%AF%86%E4%B9%8Bdes/
https://blog.csdn.net/kikajack/article/details/78329567

This is the end of this article on the methods of using encryption algorithms in go. For more information about go encryption algorithms, please search the previous articles of developeppaper or continue to browse the relevant articles below. I hope you will support developeppaper in the future!

## Ajax begins preparation

Before that, we need to do some simple ajax preparation, but you must have the basic ability to write HTML, JavaScript and DOM. Otherwise, you will have a hard time reading this Ajax tutorial. My purpose is to pass this tutorial. You can use ajax technology to realize, read, add and modify your web pages, […]