Chapter I cryptography
Section 1 Introduction to password
1, Why encrypt?
Ensure data security
Xiao Ming – > Xiao Hong:
-
After school, I'll see you in the small tree forest at the back door of the school
-
Key: + 2
-
Ciphertext: let him put in Xueen instead. Run Ruxue. Excuse me, the school. Um, after the school gate is drawn into a small version of the tree version, you can see it
-
Key (password): - 2
-
Decryption: let him put it into Xueen instead. Run Ruxue. Excuse me, the school will draw a small version of the tree version of the school door. Can you see it
-
- After school, see you at the back door of the school
2, Several common encryption algorithms
1. Encoding and decoding
2. Hash encryption
3. Symmetric encryption
4. Asymmetric encryption
5. Digital signature
3, Encryption three elements
1. Plaintext / ciphertext
2. Key
3. Encryption algorithm / decryption algorithm
Section 2 decoding and coding
1, Common coding
-
base64:26 lowercase letters, 26 uppercase letters, 10 numbers, /+
-
Base58 (block chain): remove 6 easily confused, remove 0, uppercase O, uppercase I, lowercase L, /, + (64 bits - 6 bits, 58 bits left)
-
- /, + double click to select
2, go implements base64 encoding and decoding
- code
Using: encoding/base64
input := []byte("hello world")
encodeString := base64.StdEncoding.EncodeToString(input)
Use in url:
uEnc := base64.URLEncoding.EncodeToString([]byte(input))
- decode
decodeBytes, err := base64.StdEncoding.DecodeString(encodeString)
Use in url:
uDec, err := base64.URLEncoding.DecodeString(uEnc)
3, go realizes base58 encoding, decoding and decoding
base58 coding table
[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-xwtlfxqk-1633784349826)( file:///C:/Users/ZHOUWE ~1/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg)]
Character 1 represents 0, character 2 represents 1,..., and character z represents 57
-
code
-
technological process:
-
- Convert each byte of the string into ASCII * * (256 base, 2 ^ 8 (binary) * *), and the string is actually a combination of 256 base numbers
- Convert 256 base digits to 10 base digits
- Convert hexadecimal digits to 58 hexadecimal digits (compare hexadecimal digits to 2 hexadecimal digits, constantly take remainder, and 0 is represented by code 1)
- Find the corresponding characters by comparing the 58 base digits with the 58 coding table
-
256 to decimal:
-
- h:104
- a:97
- 104*256+97=26721
-
package utils import ( "fmt" "math/big" "bytes" ) //Binary rule var b58 = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") // base58 encoding func Base58Encoding(src string) (string) { // he : 104 101 --> 104*256 + 101 = 26725 // 26725 / 58 = 15 16 17 //1. Convert string to ASCII src_byte := []byte(src) // Convert to decimal i := big.NewInt(0).SetBytes(src_byte) var mod_slice []byte // Cyclic residual //for i.Cmp(big.NewInt(0)) != 0 { for i.Cmp(big.NewInt(0)) > 0 { mod := big.NewInt(0) i58 := big.NewInt(58) // Surplus i.DivMod(i,i58,mod) // Add remainder to array mod_slice = append(mod_slice, b58[mod.Int64()]) } // Replace 0 with byte '1' for _,s := range src_byte { if s != 0 { break } mod_slice = append(mod_slice, byte('1')) } // Invert byte array //ret_mod_slice := ReverseByteArr(mod_slice) ret_mod_slice := ReverseByteArr2(mod_slice) fmt.Println(ret_mod_slice) return string(ret_mod_slice) } // byte array inversion method func ReverseByteArr(b []byte) []byte{ for i:=0; i<len(b)/2;i++ { b[i],b[len(b)-1-i] = b[len(b)-1-i],b[i] } return b } // byte array inversion mode 2 func ReverseByteArr2(b []byte) []byte{ for i,j:=0,len(b)-1;i<j;i,j = i+1,j-1{ b[i] ,b[j] = b[j],b[i] } return b } - decode // base58 decoding (reverse the encoding process) func Base58Decoding(src string) string{ // Convert to byte array src_byte := []byte(src) // What you get here is decimal ret := big.NewInt(0) for _, b := range src_byte { i := bytes.IndexByte(b58,b) fmt.Println(i) // Ride back ret.Mul(ret,big.NewInt(58)) // Add ret.Add(ret,big.NewInt(int64(i))) } return string(ret.Bytes()) }
Section 3 hash algorithm
1, Characteristics
**Irreversible: * * the original data cannot be recovered from a hash value, and the hash is not encrypted
**Uniqueness: * * there can only be one hash for a specific data, and this hash is unique
Tamper proof: changing a byte in the input data results in a completely different hash value
Registration: account and password. The password stored in the database is md5 encrypted
Login: compare the password with the password in the database through md5 coding
2, Common hash algorithms
- MD4
- MD5
- hash1
- sha224
- sha256
- sha384
- sha512
Performance: MD4 > MD5 > sha224 > sha256 > sha384 > SHA512
Memory consumption: MD5 > MD4 > SHA512 > sha384 > sha256 = sha224
It is recommended to use sha256 normally, with reliable security and low resource consumption.
3, go to implement MD4 encryption
src_byte := []byte(src) //md4 calculation md4_new := md4.New() md4Bytes := md4_new.Sum(src_byte) md4String := hex.EncodeToString(md4Bytes)
4, go implements MD5 encryption
src_byte := []byte(src) //md5 calculation md5_new := md5.New() md5Bytes := md5_new.Sum(src_byte) md5String := hex.EncodeToString(md5Bytes)
5, go implement SHA256 encryption
func GenSha256(src string) string { src_byte := []byte(src) hash := sha256.New() sha256Bytes := hash.Sum(src_byte) sha256String := hex.EncodeToString(sha256Bytes[:]) return sha256String }
Section 4 symmetric encryption
1, Characteristics
Encryption and decryption use the same key
Two way guarantee of data privacy, that is, encryption and decryption can not disclose the password
2, Advantages
High encryption efficiency, suitable for larger data encryption
3, Shortcomings
The safety is relatively asymmetric and low
4, Specific encryption method
1. AES encryption
- AES-128 encryption: key length 16 bytes
- AES-192 encryption: key length 24 bytes
- AES-256 encryption: key length 32 bytes
package utils import ( "crypto/aes" "fmt" "bytes" "encoding/base64" "errors" ) //The key can be 16, 24 or 32 bits var key []byte = []byte("hallenhallenhall") //The key is lowercase and cannot be referenced by other packages (here is the key) // Fill in the password length based on block.BlockSize(). The password length must be an integer multiple of block.BlockSize() func PadPwd(src_byte []byte,block_size int) []byte{ // Assuming that the password length is 16, the block length is 13, and the number of fillers is 16-13 = 10 pad_num := block_size - len(src_byte) % block_size ret := bytes.Repeat([]byte{byte(pad_num)},pad_num) //ret is an array of numbers to fill src_byte = append(src_byte, ret...) //Splicing ret... Is to take all the values in the array return src_byte } // encryption func AesEncoding(src string) (string,error) { src_byte := []byte(src) // safer block,err := aes.NewCipher(key) //block is an object. There are many blocks in it if err != nil { return src,err } // Password filling. The encrypted string is not enough to be an integer multiple of block.BlockSize. Fill it new_src_byte := PadPwd(src_byte,block.BlockSize()) dst := make([]byte,len(new_src_byte)) //It is used to store the encrypted results. Slices are used here block.Encrypt(dst,new_src_byte) //Encrypt dst to store the result, which is a byte array // base64 encoding pwd := base64.StdEncoding.EncodeToString(dst) return pwd,nil } // decrypt func AesDecoding(pwd string) (string,error) { pwd_byte := []byte(pwd) pwd_byte,err := base64.StdEncoding.DecodeString(pwd) if err != nil { return pwd,err } block,err_block := aes.NewCipher(key) if err_block != nil { return pwd,err_block } dst := make([]byte,len(pwd_byte)) block.Decrypt(dst,pwd_byte) //Decrypt dst to store the result, which is a byte array // The filled shall be removed dst,_ = UnPadPwd(dst) return string(dst),nil } //Used to decrypt the filled part func UnPadPwd(dst []byte) ([]byte,error) { if len(dst) <= 0 { return dst,errors.New("Incorrect length") } // The length to be filled is the length to be filled. If the best value is taken, it must be the length to be filled unpad_num := int(dst[len(dst)-1]) return dst[:(len(dst)-unpad_num)],nil //section }
2. des encryption: supports byte length of 8
package utils import ( "crypto/des" "encoding/base64" ) // Only 8 bytes in length are supported var des_key []byte = []byte("hallenha")//The key is lowercase and cannot be referenced by other packages (here is the key) // encryption func DesEncoding(src string) (string,error) { src_byte := []byte(src) block ,err := des.NewCiphe(des_key) if err != nil { return src,err } // Password filling new_src_byte := PadPwd(src_byte,block.BlockSize()) dst := make([]byte,len(new_src_byte)) block.Encrypt(dst,new_src_byte) // base64 encoding pwd := base64.StdEncoding.EncodeToString(dst) return pwd,nil } // decrypt func DesDecoding(pwd string) (string,error) { pwd_byte,err := base64.StdEncoding.DecodeString(pwd) if err != nil { return pwd,err } block,err_block := des.NewCipher(des_key) if err_block != nil { return pwd,err_block } dst := make([]byte,len(pwd_byte)) block.Decrypt(dst,pwd_byte) // The filled shall be removed dst,_ = UnPadPwd(dst) return string(dst),nil }
3. 3des encryption - CBC mode, the key length must be 24
package utils import ( "crypto/des" "encoding/base64" ) // The key of 3des is 24 in length var tdes_key []byte = []byte("hallenhallenhallenhallen") // 3des encryption func TDesEncoding(src string) (string,error) { src_byte := []byte(src) block ,err := des.**NewTripleDESCipher**(tdes_key) // And des if err != nil { return src,err } // Password filling new_src_byte := PadPwd(src_byte,block.BlockSize()) dst := make([]byte,len(new_src_byte)) block.Encrypt(dst,new_src_byte) // base64 encoding pwd := base64.StdEncoding.EncodeToString(dst) return pwd,nil } // 3des decryption func TDesDecoding(pwd string) (string,error) { pwd_byte,err := base64.StdEncoding.DecodeString(pwd) if err != nil { return pwd,err } block,err_block := des.**NewTripleDESCipher**(tdes_key) // And des if err_block != nil { return pwd,err_block } dst := make([]byte,len(pwd_byte)) block.Decrypt(dst,pwd_byte) // The filled shall be removed dst,_ = UnPadPwd(dst) return string(dst),nil }
Section V asymmetric encryption
1, Characteristics
The encryption and decryption keys are different. There are two keys (public key and private key)
Public key: a public key; Public key encryption, private key decryption
Private key: private key; Private key encryption
Private one-way guarantee, as long as one party does not disclose it, it is no problem
2, Advantages
Relatively symmetric encryption with high security
3, Shortcomings
Low encryption efficiency, suitable for small data encryption
4, Scene analysis
For which party is more important, the party will take the private key
- Login authentication
The private key is on the client, and the personal information is saved on the client
The public key is on the server to obtain personal data
If: not established
The public key is in the user's hand
The private key is on the server
- A and B are two people, and B is only allowed to read the information
Public key in A
Private key in B
If: everyone can read
Public key in B
Private key in A
5, Specific encryption method
RSA: initials of three authors
The message sender uses the other party's public key for encryption, and the message receiver uses its own private key for decryption when receiving the ciphertext
be careful:
- There should be an association between public key and key generation
- Keep the key and public key
package utils import ( "crypto/rsa" "crypto/rand" "fmt" "crypto/x509" "encoding/pem" "os" ) // Save the generated public key and key func SaveRsaKey(bits int) (error){ //privateKey is a pointer structure privateKey,err := rsa.GenerateKey(rand.Reader,bits) if err != nil { fmt.Println(err) return err } //The public key should be associated with the private key, / / privateKey is a structure publicKey := privateKey.PublicKey // Use x509 standard to encode the private key, AsN.1 encoding string x509_privete := x509.MarshalPKCS1PrivateKey(privateKey) // Use x509 standard to encode the public key and AsN.1 encodes the string x509_public := x509.MarshalPKCS1PublicKey(&publicKey)//Here, the parameter is of pointer type // Encapsulate block structure data for private key block_private := pem.Block{Type:"private key",Bytes:x509_privete} // Encapsulate block structure data for public key block_public := pem.Block{Type:"public key",Bytes:x509_public} // Create a file to store the private key with the suffix. pem privateFile,err_pri := os.Create("privateKey.pem") if err_pri != nil { return err_pri } //defer releases resources and closes the file defer privateFile.Close() //Write the private key to the file, block_private is a pointer type, and its content is obtained by taking the address character pem.Encode(privateFile,&block_private) // Create a file to store the public key with the suffix. pem publicFile,err_pub := os.Create("publicKey.pem") if err_pub != nil { return err_pub } //defer releases resources and closes the file defer publicFile.Close() //Write the public key to the file, block_public is a pointer type, and its content is obtained by taking the address character pem.Encode(publicFile,&block_public) return nil } // encryption func RsaEncoding(src ,file_path string) ([]byte,error){ src_byte := []byte(src) // Open file file,err := os.Open(file_path) if err != nil { return src_byte,err } // Get file information file_info,err_info := file.Stat() if err_info != nil { return src_byte,err_info } // Stores the slice used to read the contents of the file key_bytes := make([]byte,file_info.Size()) // Read contents into container file.Read(key_bytes) // pem decoding block,_ := pem.Decode(key_bytes) // x509 decoding publicKey ,err_pb := x509.ParsePKCS1PublicKey(block.Bytes) if err_pb != nil { return src_byte,err_pb } // Encrypt plaintext using public key ret_byte,err_ret := rsa.EncryptPKCS1v15(rand.Reader,publicKey,src_byte) if err_ret != nil { return src_byte,err_ret } return ret_byte,nil } // decrypt func RsaDecoding(src_byte []byte,file_path string) ([]byte,error) { // Open file file,err := os.Open(file_path) if err != nil { return src_byte,err } // Get file information file_info,err_info := file.Stat() if err_info != nil { return src_byte,err_info } // Read file contents key_bytes := make([]byte,file_info.Size()) // Read contents into container file.Read(key_bytes) // pem decoding block,_ := pem.Decode(key_bytes) // x509 decoding privateKey ,err_pb := x509.ParsePKCS1PrivateKey(block.Bytes) if err_pb != nil { return src_byte,err_pb } // Decrypt ret_byte, err_ret := rsa.DecryptPKCS1v15(rand.Reader,privateKey,src_byte) if err_ret != nil { return src_byte,err_ret } return ret_byte,nil }
Section VI digital signature
1, Introduction to digital signature
Digital signature is equivalent to the signature seal of paper contract
Tamper proof, camouflage proof and denial proof
rsa
- Public key encryption
- Private key decryption
rsa digital signature: (digital signature is opposite to rsa encryption, and has different purposes)
- Private key signature
- Public key verification signature
2, go implementation of digital signature algorithm
package utils import ( "crypto" "crypto/rand" "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/pem" "os" ) //Save the generated public key and key func SaveRsaSignKey(bits int)error{ //privateKey is a pointer structure privateKey, err := rsa.GenerateKey(rand.Reader, bits) if err!=nil{ return err } //privateKey is a structure. The public key should be associated with the private key publicKey := privateKey.PublicKey // Use x509 standard to encode the private key, AsN.1 encoding string x509_privete := x509.MarshalPKCS1PrivateKey(privateKey) // The x509 standard is used to encode the public key, AsN.1 encodes the string, and the parameter is a pointer x509_public := x509.MarshalPKCS1PublicKey(&publicKey) // Encapsulate block structure data for private key block_private := pem.Block{Type:"private key",Bytes:x509_privete} // Encapsulate block structure data for public key block_public := pem.Block{Type:"public key",Bytes:x509_public} // Create a file to store the private key with the suffix. pem privateFile,err_pri := os.Create("privateKey.pem") if err_pri != nil { return err_pri } //defer releases resources and closes the file defer privateFile.Close() //Write the private key to the file, block_private is a pointer type, and its content is obtained by taking the address character pem.Encode(privateFile,&block_private) // Create a file to store the public key with the suffix. pem publicFile,err_pub := os.Create("publicKey.pem") if err_pub != nil { return err_pub } //defer releases resources and closes the file defer publicFile.Close() //Write the public key to the file, block_public is a pointer type, and its content is obtained by taking the address character pem.Encode(publicFile,&block_public) return nil } //Get private key func GetPivateKey(file_path string)(*rsa.PrivateKey,error) { // Open file file,err := os.Open(file_path) if err != nil { return &rsa.PrivateKey{},err } // Get file information file_info,err_info := file.Stat() if err_info != nil { return &rsa.PrivateKey{},err_info } // Read file contents key_bytes := make([]byte,file_info.Size()) // Read contents into container file.Read(key_bytes) // pem decoding block,_ := pem.Decode(key_bytes) // x509 decoding privateKey ,err_pb := x509.ParsePKCS1PrivateKey(block.Bytes) if err_pb != nil { return &rsa.PrivateKey{},err_pb } return privateKey,nil } //Get public key func GetPublicKey(file_path string)(*rsa.PublicKey,error){ //Open file file, err := os.Open(file_path) if err!=nil{ return &rsa.PublicKey{},err } // Get file information file_info, err_info := file.Stat() if err_info != nil { return &rsa.PublicKey{},err_info } // Stores the slice used to read the contents of the file key_bytes := make([]byte,file_info.Size()) // Read contents into container file.Read(key_bytes) // pem decoding block,_ := pem.Decode(key_bytes) // x509 decoding publicKey ,err_pb := x509.ParsePKCS1PublicKey(block.Bytes) if err_pb != nil { return &rsa.PublicKey{},err_pb } return publicKey,nil } //Array signature, using private key func RsaGetSign(file_path string,src string)([]byte,error){ //Get the private key privateKey, err := GetPivateKey(file_path) if err!=nil{ return []byte{},err } hash := sha256.New() src_byte := []byte(src) hash.Write(src_byte) sha_bytes := hash.Sum(nil) //autograph signPKCS1v15, err_sign := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.*SHA256*, sha_bytes) if err!=nil{ return []byte{},err_sign } return signPKCS1v15,nil } //Verify the signature using a public key func RsaVarifySign(sign []byte,file_path string,src string)(bool,error){ publicKey, err := GetPublicKey(file_path) if err!=nil{ return false,nil } hash := sha256.New() src_byte := []byte(src) hash.Write(src_byte) sha_bytes := hash.Sum(nil) err_verify := rsa.VerifyPKCS1v15(publicKey, crypto.*SHA256*, sha_bytes, sign) if err_verify!=nil{ return false,nil } return true,nil }