Рубрики
Без рубрики

Расшифровка зашифрованных Клиентских данных Amazon Connect

Amazon Connect – это телефонная платформа Amazon, позволяющая клиентам создавать потоки вызовов, которые собирают данные… С тегами java, aws, connect, crypto.

Amazon Connect – это телефонная платформа Amazon, позволяющая клиентам создавать потоки вызовов, которые собирают данные от вызывающего абонента с помощью распознавания речи или ввода DTMF. Иногда собирается конфиденциальная информация, такая как номера кредитных карт. Connect предоставляет механизм шифрования конфиденциальных данных, пока они хранятся в службе Connect, но для обработки этих данных в рамках соответствующей интеграции лямбда-функций они должны быть расшифрованы.

Руководство и справочная реализация Amazon

Amazon предоставляет справочную реализацию в своей документации по этой функции здесь: https://docs.aws.amazon.com/connect/latest/adminguide/encrypt-data.html

Этот пост является дополнением к этой документации.

Обзор

Amazon Connect использует шифрование с открытым/закрытым ключом, используя AWS Encryption SDK для обеспечения поддержки во всем диапазоне языков, поддерживаемых этим SDK (Java, Javascript, Python и C). В то время как вам нужно будет создать и загрузить сертификат и открытый ключ для подключения к использованию, алгоритмы шифрования не настраиваются – он всегда будет использовать:

  • OAEP: Оптимальное заполнение асимметричного шифрования, описывает схему добавления рандомизированного заполнения к сообщению перед шифрованием
  • Шифрование RSA в режиме ECB: Это шифр с открытым/закрытым ключом в режиме блочного шифрования. Connect зашифрует данные с помощью открытого ключа.
  • SHA-512: Использует алгоритм SHA-512 для создания хэша сообщения, чтобы можно было обнаружить подделку сообщения.
  • MGF1: Функция генерации маски 1, часть стандарта RSA/OAEP, определенного в RFC 3447.

Это означает, очевидно, что вы должны поддерживать эти алгоритмы для расшифровки данных.

Поддержка в AWS Encryption SDK

Вы могли бы ожидать, что алгоритмы, выбранные Amazon Connect, будут поддерживаться всеми SDK для шифрования AWS. Это не так – вот краткое изложение:

Пример кода дешифрования Java

Здесь я взял образец расшифровки AWS Java и немного переработал его.

// DecryptSample.java
import com.amazonaws.encryptionsdk.AwsCrypto;
import com.amazonaws.encryptionsdk.CryptoResult;
import com.amazonaws.encryptionsdk.jce.JceMasterKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.util.*;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;

public class DecryptionSample {
    private static final String PROVIDER = "AmazonConnect";
    private static final String WRAPPING_ALGORITHM = "RSA/ECB/OAEPWithSHA-512AndMGF1Padding";
    public static void main(String[] args) throws IOException, GeneralSecurityException {
        String keyFile = args[0]; // path to PEM encoded private key to use for decryption
        String keyId = args[1]; // this is the id used for key in your contact flow
        String cypherText = args[2]; // the Base64 encoded cypher text
        decrypt(keyFile, keyId, cypherText);
    }

    public static void decrypt(String privateKeyFile, String keyId, String cypherText) throws IOException, GeneralSecurityException {
        Security.addProvider(new BouncyCastleProvider());
        byte[] cypherBytes = Base64.getDecoder().decode(cypherText);
        String privateKeyPem = new String(Files.readAllBytes(Paths.get(privateKeyFile)), Charset.forName("UTF-8"));
        RSAPrivateKey privateKey =  getPrivateKey(privateKeyPem); 
        AwsCrypto awsCrypto = new AwsCrypto();
        JceMasterKey decMasterKey = JceMasterKey.getInstance(null,privateKey, PROVIDER, keyId, WRAPPING_ALGORITHM);
        CryptoResult result = awsCrypto.decryptData(decMasterKey, cypherBytes);
        String plainText = new String(result.getResult());
        System.out.format("Decrypted: %s\n", plainText);
    }

    public static RSAPrivateKey getPrivateKey(String privateKeyPem) throws IOException, GeneralSecurityException {
        String privateKeyBase64 = privateKeyPem.replaceAll("-----.*-----\n","").replaceAll("\n", "");
        byte[] decoded = Base64.getDecoder().decode(privateKeyBase64);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded);
        RSAPrivateKey privKey = (RSAPrivateKey) kf.generatePrivate(keySpec);
        return privKey;
    }
}

Важные моменты

private static final String PROVIDER = "AmazonConnect";
String keyId = args[1]; // this is the id used for key in your contact flow
JceMasterKey decMasterKey = JceMasterKey.getInstance(null,privateKey, PROVIDER, keyId, WRAPPING_ALGORITHM);

При расшифровке зашифрованного текста AWS Encryption SDK требует, чтобы вы использовали того же поставщика и идентификаторы ключей, которые использовались при шифровании при получении ключевого контекста. Amazon Connect всегда будет использовать Amazon Connect в качестве значения поставщика. Идентификатор ключа /устанавливается вами при создании действия ввода клиента магазина в потоке вызовов. В этом примере кода мы передаем keyId в качестве параметра командной строки.

Заставить этот образец работать

  • Сохраните код как DecryptSample.java
  • Получить банки зависимостей
wget https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.9/commons-lang3-3.9.jar
wget https://repo1.maven.org/maven2/org/bouncycastle/bcprov-jdk15to18/1.64/bcprov-jdk15to18-1.64.jar
wget https://repo1.maven.org/maven2/com/amazonaws/aws-encryption-sdk-java/1.6.1/aws-encryption-sdk-java-1.6.1.jar
  • скомпилируйте код javac -cp bcprov-jdk15to18-164.jar:aws-encryption-sdk-java-1.6.1.jar DecryptionSample.java
  • запустите его с помощью java -cp bcprov-jdk15to18-164.jar:aws-encryption-sdk-java-1.6.1.jar:commons-lang3-3.9.jar:. Образец расшифровки [параметры]

Вам понадобится сертификат и пара открытых/закрытых ключей. Сначала создайте сертификат и закрытый ключ:

openssl req -batch -x509 -sha256 -nodes -newkey rsa:4096 -keyout blog.connect.private.key -days 730 -out blog.connect.certificate.pem

Затем создайте извлеките открытый ключ:

openssl x509 -pubkey -noout -in blog.connect.certificate.pem > blog.connect.public.key

Шифрование

Вот пример кода Java для выполнения шифрования, как это сделал бы Amazon Connect.

// EncryptionSample.java
import com.amazonaws.encryptionsdk.AwsCrypto;
import com.amazonaws.encryptionsdk.CryptoResult;
import com.amazonaws.encryptionsdk.jce.JceMasterKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.util.*;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;

public class EncryptionSample {
    private static final String PROVIDER = "AmazonConnect";
    private static final String WRAPPING_ALGORITHM = "RSA/ECB/OAEPWithSHA-512AndMGF1Padding";
    public static void main(String[] args) throws IOException, GeneralSecurityException {
        String keyFile = args[0]; // path to PEM encoded public key to use for encryption
        String keyId = args[1]; // this is the key id to identify the key used
        String plainText = args[2]; // this is the plain text to encypher
        encrypt(keyFile, keyId, plainText);
    }

    public static void encrypt(String publicKeyFile, String keyId, String plainText)  throws IOException, GeneralSecurityException {
        Security.addProvider(new BouncyCastleProvider());
        String publicKeyPem = new String(Files.readAllBytes(Paths.get(publicKeyFile)), Charset.forName("UTF-8"));
        RSAPublicKey publicKey =  getPublicKey(publicKeyPem);
        AwsCrypto awsCrypto = new AwsCrypto();
        JceMasterKey encMasterKey = JceMasterKey.getInstance(publicKey, null, PROVIDER, keyId, WRAPPING_ALGORITHM);
        byte[] plainBytes = plainText.getBytes();
        CryptoResult result = awsCrypto.encryptData(encMasterKey, plainBytes);
        String b64Result = Base64.getEncoder().encodeToString(result.getResult());
        System.out.println(b64Result);
    }

    public static RSAPublicKey getPublicKey(String publicKeyPem) throws IOException, GeneralSecurityException {
        String publicKeyBase64 = publicKeyPem.replaceAll("-----.*-----\n","").replaceAll("\n", "");
        byte[] decoded = Base64.getDecoder().decode(publicKeyBase64);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decoded);
        RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(keySpec);
        return pubKey;
    }
}

Шаг компиляции такой же, как и для приведенного выше кода: javac -cp bcprov-jdk15to18-164.jar:aws-encryption-sdk-java-1.6.1.jar EncryptionSample.java

Собирая все это воедино

Как только вы скомпилируете код и получите пару открытых/закрытых ключей, мы сможем его опробовать:

# assign ciphertext output to a variable
CIPHERTEXT=$(java -cp bcprov-jdk15to18-164.jar:aws-encryption-sdk-java-1.6.1.jar:commons-lang3-3.9.jar:. EncryptionSample blog.connect.public.key my-key-id 4444333322221111)
# inspect $CIPHERTEXT with:
echo $CIPHERTEXT
# try decryption
java -cp bcprov-jdk15to18-164.jar:aws-encryption-sdk-java-1.6.1.jar:commons-lang3-3.9.jar:. DecryptionSample blog.connect.private.key my-key-id "$CIPHERTEXT"
# should result in:
# Decrypted: 4444333322221111

Вывод

В этом посте рассматривалась взаимосвязь между функцией шифрования клиентского ввода Amazon Connects и SDK для шифрования, используемым для ее реализации.

Был представлен элементарный Java-код, имитирующий функциональность шифрования Amazon Connect, и сопутствующий код для его расшифровки.

Оригинал: “https://dev.to/bonybrown/decrypting-aws-connect-encrytped-data-40n8”