RSA is the most commonly used asymmetric encryption algorithm. It was proposed by Ron Rivest, Adi Shamir, and Leonard Adleman when he worked at MIT in 1977. RSA is a splicing of the first letters of the last names of the three.
Its basic principle involves the problem of factoring large integers in mathematics, that is, decomposing a large composite number (usually a huge number) into its prime factor. The security of RSA algorithm is based on the difficulty of solving this problem. There is currently no efficient method to decompose large integers in a reasonable time.
RSA supports variable-length key asymmetric encryption, and the length of file blocks that need to be encrypted is also variable.
Implement RSA
The Golang standard library iscrypto/rsaThe package implements RSA.
The following will be used to demonstrate RSA's key generation, encryption, decryption, signature and signature verification operations.
Generate a key
// GenRsaKey generates an PKCS#1 RSA keypair of the given bit size in PEM format. func GenRsaKey(bits int) (prvkey, pubkey []byte, err error) { // Generates private key. privateKey, err := (, bits) if err != nil { return } derStream := x509.MarshalPKCS1PrivateKey(privateKey) block := &{ Type: "RSA PRIVATE KEY", Bytes: derStream, } prvkey = (block) // Generates public key from private key. publicKey := & derPkix, err := (publicKey) if err != nil { return } block = &{ Type: "RSA PUBLIC KEY", Bytes: derPkix, } pubkey = (block) return }
encryption
RSA is an asymmetric encryption algorithm. Although private keys can also be used to encrypt data, since the public key is external, encrypting data is not very meaningful because everyone who knows the public key can decrypt it.
Therefore, the common practice is to use the public key to encrypt the data and decrypt the data with the private key. The private key is signed by the user, and the public key is used for signature verification.
// RsaEncrypt encrypts data using rsa public key. func RsaEncrypt(pubkey, data []byte) ([]byte, error) { block, _ := (pubkey) if block == nil { return nil, ("decode public key error") } pub, err := () if err != nil { return nil, err } return rsa.EncryptPKCS1v15(, pub.(*), data) }
Decryption
// RsaDecrypt decrypts data using rsa private key. func RsaDecrypt(prvkey, cipher []byte) ([]byte, error) { block, _ := (prvkey) if block == nil { return nil, ("decode private key error") } prv, err := x509.ParsePKCS1PrivateKey() if err != nil { return nil, err } return rsa.DecryptPKCS1v15(, prv, cipher) }
sign
// RsaSign signs using private key in PEM format. func RsaSign(prvkey []byte, hash , data []byte) ([]byte, error) { block, _ := (prvkey) if block == nil { return nil, ("decode private key error") } privateKey, err := x509.ParsePKCS1PrivateKey() if err != nil { return nil, err } // MD5 and SHA1 are not supported as they are not secure. var hashed []byte switch hash { case crypto.SHA224: h := sha256.Sum224(data) hashed = h[:] case crypto.SHA256: h := sha256.Sum256(data) hashed = h[:] case crypto.SHA384: h := sha512.Sum384(data) hashed = h[:] case crypto.SHA512: h := sha512.Sum512(data) hashed = h[:] } return rsa.SignPKCS1v15(, privateKey, hash, hashed) }
Verify your visa
// RsaVerifySign verifies signature using public key in PEM format. // A valid signature is indicated by returning a nil error. func RsaVerifySign(pubkey []byte, hash , data, sig []byte) error { block, _ := (pubkey) if block == nil { return ("decode public key error") } pub, err := () if err != nil { return err } // SHA1 and MD5 are not supported as they are not secure. var hashed []byte switch hash { case crypto.SHA224: h := sha256.Sum224(data) hashed = h[:] case crypto.SHA256: h := sha256.Sum256(data) hashed = h[:] case crypto.SHA384: h := sha512.Sum384(data) hashed = h[:] case crypto.SHA512: h := sha512.Sum512(data) hashed = h[:] } return rsa.VerifyPKCS1v15(pub.(*), hash, hashed, sig) }
/cyan
The above functions have been placed in the Golang utility librarydablelv/cyan, everyone is welcome to import it.
package main import ( stdcrypto "crypto" "fmt" "/dablelv/cyan/crypto" ) func main() { prvkey, pubkey, err := (2048) if err != nil { panic(err) } data := []byte("foo") // Encrypt data. cipher, err := (pubkey, data) if err != nil { panic(err) } if len(cipher) != 2048/8 { panic("cipher len not equal to key length") } // Decrypt data. plain, err := (prvkey, cipher) if err != nil { panic(err) } if string(data) == string(plain) { ("rsa encrypt and decrypt succeeded, data:%v plain:%v\n", string(data), string(plain)) } // Using SHA256 to hash msg and then use rsa private key to sign. sig, err := (prvkey, stdcrypto.SHA256, data) if err != nil { panic(err) } if len(sig) != 2048/8 { panic("signature len not equal to key length") } // Using public key to verify signature. err = (pubkey, stdcrypto.SHA256, data, sig) if err != nil { panic(err) } ("verify signature succeeded") }
Run output:
rsa encrypt and decrypt succeeded, data:foo plain:foo verify signature succeeded
References
Understand the encryption knowledge behind HTTPS in one article
This is the article about the implementation of Golang RSA generation keys, encryption, decryption, signature and signature verification. For more information about Golang RSA encryption and decryption, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!