Пример использования RSA
Перевод статьи "Golang & Cryptography. RSA sample"
Как вы вероятно знаете, большинство самых используемых криптографических библиотек написано на С (или С++). Go весь пропитан духом C, он небольшой но весьма эффективный язык с удобной инфраструктурой и такими низкоуровневыми возможностями, как указатели. Кроме того, Go предоставляет широкий набор фичей для более высокоуровневого программирования. Меньше кода, быстрее компиляция, быстрое исполнение - это философия Go.
Все это делает Go замечательным языком для написания криптографического приложения.
В этом примере мы научимся использовать функции из пакета crypto/rsa
.
Предположим, что Лена хочет отправить секретное сообщение Алисе. Для этого нужно выполнить ряд действий.
- Для начала, у Лены и Алисы должны быть пары ключей. Одни ключ приватный, второй публичный.
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
"os"
)
func main() {
lenaPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
fmt.Println(err.Error)
os.Exit(1)
}
lenaPublicKey := &lenaPrivateKey.PublicKey
alisaPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
fmt.Println(err.Error)
os.Exit(1)
}
alisaPublicKey := &alisaPrivateKey.PublicKey
fmt.Println("Private Key : ", lenaPrivateKey)
fmt.Println("Public key ", lenaPublicKey)
fmt.Println("Private Key : ", alisaPrivateKey)
fmt.Println("Public key ", alisaPublicKey)
}
- Лене необходимо зашифровать свое сообщение публичным ключем Алисы.
message := []byte("the code must be like a piece of music")
label := []byte("")
hash := sha256.New()
ciphertext, err := rsa.EncryptOAEP(hash, rand.Reader, alisaPublicKey, message, label
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("OAEP encrypted [%s] to \n[%x]\n", string(message), ciphertext)
Стоит обратить внимание, что OAEP этот рекомендуемый стандарт, определяющий количество байтов, добавляемых к исходной записи(padding). Стандарт PKCS1v15 стоит использовать только для поддержки старых версий протоколов.
- Далее, Лена должна подписать сообщение Алисы с помощью своего приватного ключа. Это позволит Алисе проверить отправителя сообщения с помощью Лениного публичного ключа и убедится что его отправила именно Лена.
var opts rsa.PSSOptions
opts.SaltLength = rsa.PSSSaltLengthAuto // for simple example
PSSmessage := message
newhash := crypto.SHA256
pssh := newhash.New()
pssh.Write(PSSmessage)
hashed := pssh.Sum(nil)
signature, err := rsa.SignPSS(rand.Reader, lenaPrivateKey, newhash, hashed, &opts)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("PSS Signature : %x\n", signature)
В этом случае мы выбираем PSS алгоритм. PKCS1v15 стоит использовать только для поддержки старых версий протокола.
- Теперь у Лены есть все части сообщения для отправки его Алисе.
[ciphertext, signature]
- Когда Алиса получает сообщение, первое что она должна сделать, это расшифровать его.
plainText, err := rsa.DecryptOAEP(hash, rand.Reader, alisaPrivateKey, ciphertext, label)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("OAEP decrypted [%x] to \n[%s]\n", ciphertext, plainText)
- И последний шаг, это проверка отправителя. Действительно ли сообщение отправила Лена:
err = rsa.VerifyPSS(lenaPublicKey, newhash, hashed, signature, &opts)
if err != nil {
fmt.Println("Who are U? Verify Signature failed")
os.Exit(1)
} else {
fmt.Println("Verify Signature successful")
}
Таким образом, Алиса получила сообщение, проверила отправителя и она просто вне себя от радости!
В рамках этого небольшого туториала мы создали репозиторий на GitHub с примерами кода, который вы можете использовать: github.com/brainattica/Golang-RSA-sample
В нашем следующем туториале мы попробуем экспортировать и импортировать пары RSA ключей в PEM формат.