Пакет crypto/rsa
Пакет crypto/rsa предоставляет реализацию алгоритма RSA (Rivest-Shamir-Adleman) для асимметричного шифрования и цифровых подписей. В отличие от симметричных алгоритмов, RSA использует пару ключей: открытый ключ для шифрования и проверки подписи, и закрытый ключ для расшифрования и создания подписи. Пакет поддерживает стандартные схемы заполнения PKCS#1 v1.5 и OAEP для шифрования, а также PKCS#1 v1.5 и PSS для подписей.
Базовые типы
type PrivateKey struct {
PublicKey
D *big.Int
Primes []*big.Int
Precomputed struct {
Dp *big.Int
Dq *big.Int
Qinv *big.Int
}
}
type PublicKey struct {
N *big.Int
E int
}
Пакет определяет два основных типа: PublicKey для открытого ключа, содержащий модуль N и открытую экспоненту E, и PrivateKey для закрытого ключа, который встраивает открытый ключ и содержит секретную экспоненту D и простые множители.
Генерация ключевой пары
package main
import (
"crypto/rand"
"crypto/rsa"
"fmt"
)
func main() {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
fmt.Printf("Failed to generate key: %v\n", err)
return
}
fmt.Printf("Private key generated with %d-bit modulus\n", privateKey.N.BitLen())
fmt.Printf("Public key exponent: %d\n", privateKey.E)
}
Результат выполнения кода:
"Private key generated with 2048-bit modulus"
"Public key exponent: 65537"
Функция GenerateKey создает новую пару ключей RSA с указанной длиной модуля в битах. В качестве первого параметра передается криптографически безопасный генератор случайных чисел, вторым параметром - желаемая длина ключа (рекомендуется 2048 бит и выше). Функция возвращает указатель на PrivateKey и ошибку.
Шифрование с открытым ключом (PKCS#1 v1.5)
package main
import (
"crypto/rand"
"crypto/rsa"
"fmt"
)
func main() {
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
publicKey := &privateKey.PublicKey
message := []byte("Secret message")
ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, message)
if err != nil {
fmt.Printf("Encryption failed: %v\n", err)
return
}
fmt.Printf("Ciphertext length: %d bytes\n", len(ciphertext))
}
Результат выполнения кода:
"Ciphertext length: 256 bytes"
Функция EncryptPKCS1v15 шифрует сообщение с использованием открытого ключа по схеме PKCS#1 v1.5. Первым параметром передается источник случайных чисел, вторым - открытый ключ, третьим - байтовый срез сообщения. Длина сообщения должна быть меньше длины ключа минус минимум 11 байт (для схемы заполнения).
Расшифрование с закрытым ключом (PKCS#1 v1.5)
package main
import (
"crypto/rand"
"crypto/rsa"
"fmt"
)
func main() {
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
publicKey := &privateKey.PublicKey
message := []byte("Secret message")
ciphertext, _ := rsa.EncryptPKCS1v15(rand.Reader, publicKey, message)
plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, ciphertext)
if err != nil {
fmt.Printf("Decryption failed: %v\n", err)
return
}
fmt.Printf("Decrypted message: %s\n", string(plaintext))
}
Результат выполнения кода:
"Decrypted message: Secret message"
Функция DecryptPKCS1v15 расшифровывает зашифрованное сообщение с использованием закрытого ключа по схеме PKCS#1 v1.5. Первым параметром передается источник случайных чисел (необходим для защиты от атак по времени), вторым - закрытый ключ, третьим - байтовый срез шифротекста.
Шифрование с OAEP (Optimal Asymmetric Encryption Padding)
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
)
func main() {
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
publicKey := &privateKey.PublicKey
message := []byte("Sensitive data")
label := []byte("")
ciphertext, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, message, label)
if err != nil {
fmt.Printf("OAEP encryption failed: %v\n", err)
return
}
fmt.Printf("OAEP ciphertext length: %d bytes\n", len(ciphertext))
}
Результат выполнения кода:
"OAEP ciphertext length: 256 bytes"
Функция EncryptOAEP использует более современную схему заполнения OAEP, которая обеспечивает лучшую криптографическую стойкость. Первым параметром передается хеш-функция, вторым - источник случайных чисел, третьим - открытый ключ, четвертым - сообщение, пятым - опциональная метка (обычно пустой срез).
Расшифрование с OAEP
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
)
func main() {
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
publicKey := &privateKey.PublicKey
message := []byte("Sensitive data")
label := []byte("")
ciphertext, _ := rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, message, label)
plaintext, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, ciphertext, label)
if err != nil {
fmt.Printf("OAEP decryption failed: %v\n", err)
return
}
fmt.Printf("Decrypted OAEP message: %s\n", string(plaintext))
}
Результат выполнения кода:
"Decrypted OAEP message: Sensitive data"
Функция DecryptOAEP расшифровывает сообщение, зашифрованное с помощью OAEP. Параметры аналогичны функции шифрования, но вместо открытого ключа используется закрытый.
Создание цифровой подписи (PKCS#1 v1.5)
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
)
func main() {
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
message := []byte("Important document")
hash := sha256.Sum256(message)
signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hash[:])
if err != nil {
fmt.Printf("Signing failed: %v\n", err)
return
}
fmt.Printf("Signature length: %d bytes\n", len(signature))
}
Результат выполнения кода:
"Signature length: 256 bytes"
Функция SignPKCS1v15 создает цифровую подпись по схеме PKCS#1 v1.5. Первым параметром передается источник случайных чисел, вторым - закрытый ключ, третьим - алгоритм хеширования, четвертым - хеш сообщения.
Проверка цифровой подписи (PKCS#1 v1.5)
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
)
func main() {
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
publicKey := &privateKey.PublicKey
message := []byte("Important document")
hash := sha256.Sum256(message)
signature, _ := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hash[:])
err := rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hash[:], signature)
if err != nil {
fmt.Printf("Verification failed: %v\n", err)
} else {
fmt.Println("Signature is valid")
}
}
Результат выполнения кода:
"Signature is valid"
Функция VerifyPKCS1v15 проверяет подпись PKCS#1 v1.5. Первым параметром передается открытый ключ, вторым - алгоритм хеширования, третьим - хеш сообщения, четвертым - подпись. Возвращает ошибку, если подпись недействительна.
Создание подписи PSS (Probabilistic Signature Scheme)
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
)
func main() {
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
message := []byte("Secure document")
hash := sha256.Sum256(message)
opts := &rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthAuto,
Hash: crypto.SHA256,
}
signature, err := rsa.SignPSS(rand.Reader, privateKey, crypto.SHA256, hash[:], opts)
if err != nil {
fmt.Printf("PSS signing failed: %v\n", err)
return
}
fmt.Printf("PSS signature length: %d bytes\n", len(signature))
}
Результат выполнения кода:
"PSS signature length: 256 bytes"
Функция SignPSS создает подпись с использованием более современной схемы PSS, которая обеспечивает доказуемую стойкость. Параметры включают опции PSSOptions, где можно настроить длину соли.
Проверка подписи PSS
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
)
func main() {
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
publicKey := &privateKey.PublicKey
message := []byte("Secure document")
hash := sha256.Sum256(message)
opts := &rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthAuto,
Hash: crypto.SHA256,
}
signature, _ := rsa.SignPSS(rand.Reader, privateKey, crypto.SHA256, hash[:], opts)
err := rsa.VerifyPSS(publicKey, crypto.SHA256, hash[:], signature, opts)
if err != nil {
fmt.Printf("PSS verification failed: %v\n", err)
} else {
fmt.Println("PSS signature is valid")
}
}
Результат выполнения кода:
"PSS signature is valid"
Функция VerifyPSS проверяет подпись PSS. Параметры аналогичны функции SignPSS, включая опции, которые должны совпадать с использованными при создании подписи.
Смотрите также
-
функцию
rsa.GenerateKey,
которая генерирует новую пару ключей RSA -
функцию
rsa.EncryptPKCS1v15,
которая шифрует данные по схеме PKCS#1 v1.5 -
функцию
rsa.EncryptOAEP,
которая шифрует данные с использованием OAEP -
функцию
rsa.SignPSS,
которая создает подпись по схеме PSS