Blockchain cryptography

Posted by LanceEh on Sat, 09 Oct 2021 15:20:50 +0200

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

  1. base64:26 lowercase letters, 26 uppercase letters, 10 numbers, /+

  2. 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

  1. 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

  1. 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
 }

Topics: Blockchain Algorithm