This is a creation in Article, where the information may have evolved or changed.
Golang Encryption series of the last article, well, RSA involves too many concepts, it took a long time to figure out ...
The structure of the code is as
Ps:staruml this thing on Mac all the lines that connect to interface become straight ... I am very melancholy ...
Define an Open Interface
Package Rsaimport "Crypto" type Cipher interface {Encrypt (plaintext []byte) ([]byte, error) Decrypt (ciphertext []byte) ([]byte, error) sign (src []byte, hash crypto. hash) ([]byte, error) Verify (src []byte, sign []byte, hash crypto. Hash) Error}
Defines the private pkcsclient, implements the cipher interface, and the PKCS-formatted private key uses this client
package rsaimport ( "crypto" "Crypto/rand" " Crypto/rsa ") Type pkcsclient struct { privatekey *rsa. Privatekey publickey *rsa. publickey}func (this *pkcsclient) encrypt (plaintext []byte) ([]byte, error) { return rsa. Encryptpkcs1v15 (Rand. Reader, this.publickey, plaintext)}func (this *pkcsclient) Decrypt (ciphertext [] BYTE) ([]byte, error) { return rsa. Decryptpkcs1v15 (Rand. Reader, this.privatekey, ciphertext)}func (this *pkcsclient) Sign (Src []byte, hash crypto. Hash) ([]byte, error) { h := hash. New () h.write (SRC) hashed := h.sum (nil) return rsa. Signpkcs1v15 (Rand. Reader, this.privatekey, hash, hashed)}func (this *pkcsclient) verify (Src []byte, sign []byte, hash crypto. Hash) error { h := hash. New () h.write (SRC) hashed := h.sum (nil) return rsa. Verifypkcs1v15 (This.publickey, hash, hashed, sign)}
Defining a private key type as an enumeration type
Package Privatekeytype type Int64const (PKCS1 type = Iota PKCS8)
Defines a new/newdefault function that is used to create a client
package rsaimport ( "Crypto/rsa" "crypto/x509" " Encoding/pem " " errors " " Toast/rsa/privatekey ")//default client, PKCS8 private key format, PEM encoded func newdefault (privatekey, publickey string) (cipher, error) { Blockpri, _ := pem. Decode ([]byte (Privatekey)) if blockPri == nil { return nil, errors. New ("Private key error") } blockpub, _ := pem. Decode ([]byte (PublicKey)) if blockPub == nil { return nil, errors. New ("Public key error") } return new (blockPri.Bytes, Blockpub.bytes, privatekey. PKCS8)}func new (Privatekey, publickey []byte, privatekeytype privatekey. Type) (Cipher, error) { prikey, err := genprikey (privateKey, Privatekeytype) if err != nil { return nil, err } pubkey, err := genpubkey (PublicKey) if err != nil { return nil, err } return &pkcsClient{privateKey: priKey, Publickey: pubkey}, nil}func genpubkey (publickey []byte) (*rsa. Publickey, error) { pub, err := x509. Parsepkixpublickey (PublicKey) if err != nil { return nil, err } return pub. (*rsa. PublicKey), nil}func genprikey (Privatekey []byte, privatekeytype privatekey. Type) (*rsa. Privatekey, error) { var prikey *rsa. privatekey var err error switch privatekeytype { case privatekey. pkcs1: { prikey, err = x509. Parsepkcs1privatekey ([]byte (Privatekey)) if err != nil { return nil, err } } case privatekey. pkcs8: { prki, err := x509. Parsepkcs8privatekey ([]byte (Privatekey)) if err != nil { return nil, err } prikey = prki. (*rsa. Privatekey) } default: { return nil, errors. New ("Unsupport private key type") } } return prikey, nil}
Finally, see how to use the above code for encryption/decryption, signature verification
package rsa_testimport ( "crypto" "Encoding/base64" "Encoding/hex" "FMT" "testing" "Toast/rsa") var Cipher rsa. Cipherfunc init () { client, err := rsa. Newdefault ('-----begin private key-----Private Key Information-----end private key-----', '-----BEGIN public key-----Public Key Information-----end public key-----') if err != Nil { fmt. PRINTLN (Err) } cipher = client}func test_defaultclient (t *testing. T) { cp, err := cipher. Encrypt ([]byte ("Test Encryption Decryption")) if err != nil { t.error (Err) } cpstr := base64. Urlencoding.encodetostring (CP) fmt.Println (CPSTR) ppby, err := base64. Urlencoding.decodestring (CPSTR) if err != nil { t.error (Err) } pp, err := cipher. Decrypt (PPBY) fmt. Println (String (PP))}func test_sign_defaultclient (t *testing. T) { src := "test signature Verification" signbytes, err := cipher. sign ([]byte (SRC), crypto. SHA256) if err != nil { t.error (ERR) } sign := hex. Encodetostring (signbytes) fmt. PRINTLN (sign) signb, err := hex. Decodestring (sign) errv := cipher. Verify ([]byte (SRC), signb, crypto. SHA256) if errv != nil { t.erroR (ERRV) } fmt. Println ("Verify success")}
For some of the concepts associated with RSA, see my other blog. A bloodbath-induced murder
There is also a well-written aes/rsa and decryption package, can be directly referenced, GitHub address: Https://github.com/89hmdys/toast