GoProg

 
Топ хэштегов


Архив

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 #криптография #программирование #шифрование



Новый комментарий: