
RSA - широко используемый криптографический алгоритм, построенный на шифрование с открытым ключом. Значение его трудно не оценить. В этом посте мы расскажем вам, как работать с ним на Go. К счастью, стандартная библиотека языка содержит все необходимое.
Во-первых, для работы с алгоритмом сгенерируем пару приватный/публичный ключ. Для этого нам понадобятся следующие библиотеки: crypto/rand, crypto/rsa. Пример генерации ниже:
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
publicKey := privateKey.PublicKey
В данном примере мы генерируем 2048 битный приватный ключ и получаем парный к нему публичный. Теперь давайте попробуем зашифровать некоторое сообщение с использованием приватного ключа и алгоритма OAEP (Optimal Asymmetric Encryption Padding, Оптимальное асимметричное шифрование с дополнением).
Алгоритм OAEP применяется для предварительной обработки сообщения перед использованием RSA. Сначала сообщение дополняется до фиксированной длины с помощью OAEP, затем шифруется с помощью RSA. Совместно, такая схема шифрования получила название RSA-OAEP и является частью действующего стандарта шифрования с открытым ключом RFC 8017.
Пример шифрующей функции ниже:
func RSA_OAEP_Encrypt(secretMessage string, key rsa.PublicKey) string {
label := []byte("OAEP Encrypted")
rng := rand.Reader
ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, &key,
[]byte(secretMessage), label)
CheckError(err)
return base64.StdEncoding.EncodeToString(ciphertext)
}
Теперь давайте попробуем расшифровать наше сообщение при помощи нашего приватного ключа, это делаем следующим образом:
func RSA_OAEP_Decrypt(cipherText string, privKey rsa.PrivateKey) string {
ct, _ := base64.StdEncoding.DecodeString(cipherText)
label := []byte("OAEP Encrypted")
rng := rand.Reader
plaintext, err := rsa.DecryptOAEP(sha256.New(), rng, &privKey, ct, label)
CheckError(err)
fmt.Println("Plaintext:", string(plaintext))
return string(plaintext)
}
Ниже приведет пример полной программы, использующей эти функции:
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"encoding/base64"
"fmt"
)
func main() {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
CheckError(err)
publicKey := privateKey.PublicKey
secretMessage := "This is super secret message!"
encryptedMessage := RSA_OAEP_Encrypt(secretMessage, publicKey)
fmt.Println("Cipher Text:", encryptedMessage)
RSA_OAEP_Decrypt(encryptedMessage, *privateKey)
}
func CheckError(e error) {
if e != nil {
fmt.Println(e.Error)
}
}
func RSA_OAEP_Encrypt(secretMessage string, key rsa.PublicKey) string {
label := []byte("OAEP Encrypted")
rng := rand.Reader
ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, &key,
[]byte(secretMessage), label)
CheckError(err)
return base64.StdEncoding.EncodeToString(ciphertext)
}
func RSA_OAEP_Decrypt(cipherText string, privKey rsa.PrivateKey) string {
ct, _ := base64.StdEncoding.DecodeString(cipherText)
label := []byte("OAEP Encrypted")
rng := rand.Reader
plaintext, err := rsa.DecryptOAEP(sha256.New(), rng, &privKey, ct, label)
CheckError(err)
fmt.Println("Plaintext:", string(plaintext))
return string(plaintext)
}
Пример работы программы ниже:
Cipher Text: sg2tLe8UL9/OrtOx9fHFhnWsKulgBDCiREZX
HpAZucl41UrBAQj0i3Vjhd+tSFmyH/buWYzRx+/+KS5JdTo6S
47qPM8GhNv8Qqp8F/gUtr2dsLyvUajHIhxHzccNv5vcYYnBtT
ZXixyTwpj4jj+GRur8C3xNwGYx/5xbnpiHMcYqNAWtLY3tE7l
61f5Lgpphnl3Y2fro/wdy+yRzmTWef5oPz2/PNaI/kz6yq/Bl
nx/63k1Rut3nPFFbXX6bm4GyEiwcWFfNkzbiCMjdYHXnQ2Snv
fKF4DGd0MeYQGeb01p+hKUD4M01ckSaeht16y5+vl2BcafTa4
wNsplgm7/yOA==
Plaintext: This is super secret message!
Теперь давайте попробуем сгенерировать цифровую подпись для нашего исходного сообщения, используя приватный ключ и алгоритм PKCS1v15:
func RSA_PKCS_Sing(message string, key *rsa.PrivateKey) string {
rng := rand.Reader
hashed := sha256.Sum256([]byte(message))
signature, err := rsa.SignPKCS1v15(rng, key, crypto.SHA256, hashed[:])
if err != nil {
panic(err)
}
return base64.StdEncoding.EncodeToString(signature)
}
Для проверки воспользуемся следующим кодом:
func RSA_PKCS_Verify(message string, key *rsa.PublicKey, signature string) error {
sign, _ := base64.StdEncoding.DecodeString(signature)
hashed := sha256.Sum256([]byte(message))
return rsa.VerifyPKCS1v15(key, crypto.SHA256, hashed[:], sign)
}
Полный код программы ниже:
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"encoding/base64"
"fmt"
)
func main() {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
CheckError(err)
publicKey := privateKey.PublicKey
myMessage := "Hello, World!"
sign := RSA_PKCS_Sing(myMessage,privateKey)
fmt.Println("Signature:", sign)
valid := RSA_PKCS_Verify(myMessage, &publicKey, sign)
fmt.Println("Valid:",valid==nil)
}
func CheckError(e error) {
if e != nil {
fmt.Println(e.Error)
}
}
func RSA_PKCS_Sing(message string, key *rsa.PrivateKey) string {
rng := rand.Reader
hashed := sha256.Sum256([]byte(message))
signature, err := rsa.SignPKCS1v15(rng, key, crypto.SHA256, hashed[:])
if err != nil {
panic(err)
}
return base64.StdEncoding.EncodeToString(signature)
}
func RSA_PKCS_Verify(message string, key *rsa.PublicKey, signature string) error {
sign, _ := base64.StdEncoding.DecodeString(signature)
hashed := sha256.Sum256([]byte(message))
return rsa.VerifyPKCS1v15(key, crypto.SHA256, hashed[:], sign)
}
Результат работы:
Signature: ifDuXRxYvLgZqEuJMAmlWmD62MKhya5f4
v2+KkZ4rHZYro5k49sBOI9aTUciKXehqTX3O0GUGJdnz
2qqr+IUv1bFfuw75RKXAWU2dF1BZ1FyFoIfoLJvJMTO/
806LKnFkWDLyVkZmKpJFhLGxNUssBDPhPu72NszeeBeL
cYFKCI9vTjmQK3fibs2u3yftRB01IpZS4bk80lRL7lE7
vI3GlBWKG24Kutum5RON0yvKiteTLBX19ncvGxbR6wi0
eZ5zHUpjd2x4UmrcRFvL8daQNK7GJ0A0ssKNw/Wv5xIs
fQEP+LPQpvPuEC1jGYNymMbf1g4nQcqg/04uvFRfijeW
g==
Valid: true
#crypto #Go #golang #IT #OAEP #PKCS #RSA #криптография #программирование #шифрование