Асимметричное шифрование данных
В этом разделе вы узнаете, как в KMS шифровать и расшифровывать данные по схеме асимметричного шифрования.
Перед началом работы
Шифрование в командной строке Bash по этой инструкции выполняется с помощью утилиты OpenSSL
Выполните команду:
sudo apt-get install openssl
Воспользуйтесь пакетным менеджером Chocolatey
choco install openssl
Зашифруйте данные
-
Если у вас еще нет ключевой пары шифрования, создайте ее.
-
Получите открытый ключ шифрования и сохраните его:
Консоль управленияCLIAPI- В консоли управления
выберите каталог, в котором находится нужная ключевая пара. - В списке сервисов выберите Key Management Service.
- На панели слева выберите Асимметричные ключи.
- Перейдите на вкладку Шифрование.
- В строке с нужной ключевой парой нажмите значок
и выберите Публичный ключ. - В открывшемся окне нажмите кнопку Скачать, чтобы скачать публичный ключ шифрования.
Если у вас еще нет интерфейса командной строки Yandex Cloud, установите и инициализируйте его.
По умолчанию используется каталог, указанный в профиле CLI. Вы можете указать другой каталог с помощью параметра
--folder-name
или--folder-id
.-
Посмотрите описание команды CLI для получения открытого ключа шифрования:
yc kms asymmetric-encryption-crypto get-public-key --help
-
Получите идентификатор каталога, в котором сохранена ключевая пара шифрования.
-
Получите идентификатор нужной ключевой пары шифрования, указав идентификатор каталога:
yc kms asymmetric-encryption-key list \ --folder-id <идентификатор_каталога>
Результат:
+----------------------+-----------------------+---------------------------+---------------------+--------+ | ID | NAME | ENCRYPTION ALGORITHM | CREATED AT | STATUS | +----------------------+-----------------------+---------------------------+---------------------+--------+ | abjfmo5enqlr******** | sample-encryption-key | RSA_2048_ENC_OAEP_SHA_256 | 2023-08-16 18:10:03 | ACTIVE | +----------------------+-----------------------+---------------------------+---------------------+--------+
-
Получите открытый ключ шифрования, указав полученный ранее идентификатор ключевой пары:
yc kms asymmetric-encryption-crypto get-public-key \ --id <идентификатор_ключевой_пары>
Результат:
key_id: abj9g2dil5sj******** public_key: | -----BEGIN PUBLIC KEY----- MIIB... ...QAB -----END PUBLIC KEY-----
Сохраните полученный ключ в файл, например, в файл
public.key
. Убедитесь, что в файле отсутствуют пробелы в начале строк.
Чтобы получить открытый ключ шифрования, воспользуйтесь вызовом gRPC API AsymmetricEncryptionCryptoService/GetPublicKey.
- В консоли управления
-
Зашифруйте файл с сообщением:
Примечание
Размер шифруемого сообщения зависит от длины ключа шифрования и длины хэш-функции.
BashJavaGoPythonВ терминале выполните команду:
openssl pkeyutl \ -in <путь_к_файлу_с_сообщением> \ -encrypt \ -pubin \ -inkey <путь_к_файлу_с_публичным_ключом> \ -pkeyopt rsa_padding_mode:oaep \ -pkeyopt rsa_oaep_md:sha256 \ -pkeyopt rsa_mgf1_md:sha256 | base64 > <путь_к_файлу_с_шифртекстом>
Где:
-in
— путь к файлу с сообщением, которое нужно зашифровать.-inkey
— путь к файлу с публичным ключом шифрования.<путь_к_файлу_с_шифртекстом>
— путь к файлу, в котором будет сохранено зашифрованное сообщение.
В результате выполнения команды зашифрованное сообщение сохранится в указанном файле в кодировке
base64
.import org.bouncycastle.util.io.pem.PemObject; import org.bouncycastle.util.io.pem.PemReader; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.io.IOException; import java.io.StringReader; import java.security.*; import java.security.spec.*; import java.util.Base64; public class EncryptRsa { public static void main(String[] args) throws Exception { String plaintext = "<сообщение>"; String publicKeyPem = """ -----BEGIN PUBLIC KEY----- <содержимое_открытого_ключа> -----END PUBLIC KEY-----"""; byte[] cipherTextBytes = encryptWithRsaOaep(plaintext, publicKeyPem); System.out.println(Base64.getEncoder().encodeToString(cipherTextBytes)); } private static byte[] encryptWithRsaOaep(String plaintext, String publicKeyPem) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { // Parsing PEM-encoded public key PemReader pemReader = new PemReader(new StringReader(publicKeyPem)); PemObject pemObject = pemReader.readPemObject(); byte[] publicKeyBytes = pemObject.getContent(); // Creating a PublicKey object from encoded key bytes X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); // Creating a Cipher object for encryption Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); // Text encryption byte[] plaintextBytes = plaintext.getBytes(); // return cipher bytes return cipher.doFinal(plaintextBytes); } }
Где:
<сообщение>
— текст сообщения, которое нужно зашифровать.<содержимое_открытого_ключа>
— содержимое открытого ключа шифрования.
Шифрование выполняется по алгоритму RSA
сOAEP
иSHA-256
. Код вернет шифртекст в формате строки в кодировкеbase64
.import ( "crypto" "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "fmt" "log" ) func runRsaEncryption() { plaintext := "<сообщение>" publicKeyPem := `-----BEGIN PUBLIC KEY----- <содержимое_открытого_ключа> -----END PUBLIC KEY-----` ciphertextBytes := encryptRSA(publicKeyPem, plaintext, crypto.SHA256) ciphertextBase64 := base64.StdEncoding.EncodeToString(ciphertextBytes) fmt.Println("Ciphertext:", ciphertextBase64) } func encryptRSA(publicKeyPem string, plaintext string, hash crypto.Hash) []byte { block, _ := pem.Decode([]byte(publicKeyPem)) if block == nil { log.Fatal("failed to decode PEM block containing public key") } pub, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { log.Fatal(err) } publicKey, ok := pub.(*rsa.PublicKey) if !ok { log.Fatal("not RSA public key") } ciphertext, err := rsa.EncryptOAEP(hash.New(), rand.Reader, publicKey, []byte(plaintext), nil) if err != nil { log.Fatal(err) } return ciphertext }
Где:
<сообщение>
— текст сообщения, которое нужно зашифровать.<содержимое_открытого_ключа>
— содержимое открытого ключа шифрования.
Шифрование выполняется по алгоритму RSA
сOAEP
иSHA-256
. Код вернет шифртекст в формате строки в кодировкеbase64
.from cryptography.hazmat.primitives.asymmetric import rsa, padding from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import serialization # Define hash algorithms and corresponding salt lengths def encrypt_with_rsa_oaep(plaintext, public_key_string, hash_algorithm): hash_algorithms = { 'SHA256': hashes.SHA256, 'SHA384': hashes.SHA384, 'SHA512': hashes.SHA512 } # Check if the provided hash algorithm is supported if hash_algorithm not in hash_algorithms: raise ValueError('Unsupported hash algorithm: ' + hash_algorithm) # Loading a PEM Encoded Public Key public_key = serialization.load_pem_public_key( public_key_string.encode() ) # Text encryption ciphertext = public_key.encrypt( plaintext.encode(), padding.OAEP( mgf=padding.MGF1(algorithm=hash_algorithms[hash_algorithm]()), algorithm=hash_algorithms[hash_algorithm](), label=None ) ) # Return ciphertext in Byte array format return ciphertext def test_encrypt_text(): plaintext = "<сообщение>" public_key_string = """ -----BEGIN PUBLIC KEY----- <содержимое_открытого_ключа> -----END PUBLIC KEY-----""" ciphertext = encrypt_with_rsa_oaep(plaintext, public_key_string,'SHA256') ciphertext_base64 = base64.b64encode(ciphertext).decode() print("Ciphertext:", ciphertext_base64)
Где:
<сообщение>
— текст сообщения, которое нужно зашифровать.<содержимое_открытого_ключа>
— содержимое открытого ключа шифрования.
Шифрование выполняется по алгоритму RSA
сOAEP
иSHA-256
. Код вернет шифртекст в формате строки в кодировкеbase64
.
Расшифруйте данные
Если у вас еще нет интерфейса командной строки Yandex Cloud, установите и инициализируйте его.
По умолчанию используется каталог, указанный в профиле CLI. Вы можете указать другой каталог с помощью параметра --folder-name
или --folder-id
.
-
Посмотрите описание команды CLI для расшифрования данных с помощью закрытого ключа шифрования:
yc kms asymmetric-encryption-crypto decrypt --help
-
Получите идентификатор каталога, в котором сохранена ключевая пара шифрования.
-
Получите идентификатор нужной ключевой пары шифрования, указав идентификатор каталога:
yc kms asymmetric-encryption-key list \ --folder-id <идентификатор_каталога>
Результат:
+----------------------+-----------------------+---------------------------+---------------------+--------+ | ID | NAME | ENCRYPTION ALGORITHM | CREATED AT | STATUS | +----------------------+-----------------------+---------------------------+---------------------+--------+ | abjfmo5enqlr******** | sample-encryption-key | RSA_2048_ENC_OAEP_SHA_256 | 2023-08-16 18:10:03 | ACTIVE | +----------------------+-----------------------+---------------------------+---------------------+--------+
-
Расшифруйте шифртекст:
yc kms asymmetric-encryption-crypto decrypt \ --id <идентификатор_ключевой_пары> \ --ciphertext-file <путь_к_файлу_с_шифртекстом> \ --plaintext-file <путь_к_файлу_с_расшифрованным_сообщением> \ --inform base64
Где:
--id
— полученный ранее идентификатор ключевой пары шифрования.--ciphertext-file
— путь к файлу, содержащему шифртекст в кодировкеbase64
.--plaintext-file
— путь к файлу, в который будет расшифровано сообщение.
Результат:
key_id: abjt22qubivb******** plaintext: 0KHQv...QuSE=
В результате выполнения команды зашифрованное сообщение будет расшифровано закрытым ключом шифрования в KMS, а расшифрованный текст сохранится в указанном файле.
Чтобы расшифровать данные, воспользуйтесь вызовом gRPC API AsymmetricEncryptionCryptoService/Decrypt.