

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Validar os resultados da consulta salva pelo CloudTrail Lake
<a name="cloudtrail-query-results-validation"></a>

Para determinar se os resultados da consulta foram modificados, excluídos ou inalterados após a CloudTrail entrega dos resultados da consulta, você pode usar a validação de integridade dos resultados da CloudTrail consulta. Esse recurso é criado usando algoritmos padrão do setor: SHA-256 para hashing e SHA-256 com RSA para assinaturas digitais. Isso torna computacionalmente inviável modificar, excluir ou falsificar arquivos de resultados de CloudTrail consultas sem detecção. Você pode usar a linha de comando para validar os arquivos de resultados de consulta. 

## Por que usá-la?
<a name="cloudtrail-query-results-validation-use-cases"></a>

Os arquivos de resultado de consulta validados são valiosíssimos para segurança e investigações forenses. Por exemplo, um arquivo de resultado de consulta validado permite que você afirme positivamente que o arquivo de resultados da consulta em si não foi alterado. O processo de validação da integridade do arquivo de resultados da CloudTrail consulta também permite que você saiba se um arquivo de resultado da consulta foi excluído ou alterado. 

**Topics**
+ [Por que usá-la?](#cloudtrail-query-results-validation-use-cases)
+ [Valide os resultados da consulta salvos com o AWS CLI](#cloudtrail-query-results-validation-cli)
+ [CloudTrail estrutura de arquivo de assinatura](#cloudtrail-results-file-validation-sign-file-structure)
+ [Implementações personalizadas da validação da integridade do arquivo de resultados da CloudTrail consulta](#cloudtrail-results-file-custom-validation)

## Valide os resultados da consulta salvos com o AWS CLI
<a name="cloudtrail-query-results-validation-cli"></a>

É possível validar a integridade dos arquivos de resultado de consultas e do arquivo de assinatura com o comando [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/cloudtrail/verify-query-results.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/cloudtrail/verify-query-results.html).

### Pré-requisitos
<a name="cloudtrail-query-results-validation-cli-prerequisites"></a>

Para validar a integridade dos resultados de consulta com a linha de comando, é necessário satisfazer as seguintes condições:
+ Você deve ter conectividade on-line com AWS.
+ Você deve usar a AWS CLI versão 2.
+ Para validar arquivos de resultados de consulta e o arquivo de assinatura localmente, as seguintes condições se aplicam:
  + É necessário colocar os arquivos de resultados de consulta e o arquivo de assinatura no caminho de arquivo especificado. Especifique o caminho do arquivo como o valor do parâmetro **--local-export-path**.
  + Você não deve renomear os arquivos de resultados de consulta e o arquivo de assinatura.
+ Para validar os arquivos de resultados de consulta e o arquivo de assinatura no bucket do S3, as seguintes condições se aplicam:
  + Você não deve renomear os arquivos de resultados de consulta e o arquivo de assinatura.
  + É necessário ter acesso de leitura ao bucket do Amazon S3 que contém os arquivos de resultado de consultas e de assinatura.
  + O prefixo do S3 especificado deve conter os arquivos de resultados de consulta e o arquivo de assinatura. Especifique o prefixo do S3 como o valor do parâmetro **--s3-prefix**.

### verify-query-results
<a name="cloudtrail-query-results-validation-cli-command"></a>

 O comando **verify-query-results** verifica o valor de hash de cada arquivo de resultado de consulta, comparando o valor com `fileHashValue` no arquivo de assinatura e, em seguida, validando o valor `hashSignature` no arquivo de assinatura. 

Ao verificar os resultados da consulta, você pode usar as opções de linha de comando **--s3-bucket** e **--s3-prefix** para validar os arquivos de resultados de consulta e o arquivo de assinatura armazenados em um bucket do S3 ou pode usar a opção de linha de comando **--local-export-path** para realizar uma validação local dos arquivos de resultados de consulta e do arquivo de assinatura baixados.

**nota**  
O comando **verify-query-results** é específico da região. Você deve especificar a opção **--region** global para validar os resultados da consulta para uma específica Região da AWS.

Veja a seguir as opções para o comando **verify-query-results**.

**--s3-bucket** {{<string>}}  
Especifica o nome do bucket do S3 que armazena os arquivos de resultados de consulta e o arquivo de assinatura. Não é possível usar esse parâmetro com **--local-export-path**.

**--s3-prefix** {{<string>}}  
Especifica o caminho do S3 da pasta do S3 que contém os arquivos de resultados de consulta e o arquivo de assinatura (por exemplo, `s3/path/`). Não é possível usar esse parâmetro com **--local-export-path**. Esse parâmetro não precisará ser fornecido se os arquivos estiverem localizados no diretório raiz do bucket do S3.

**--local-export-path** {{<string>}}  
Especifica o diretório local que contém os arquivos de resultados de consulta e o arquivo de assinatura (por exemplo, `/local/path/to/export/file/`). Não é possível usar esse parâmetro com **--s3-bucket** ou **--s3-prefix**.

#### Exemplos
<a name="cloudtrail-query-results-validation-cli-examples"></a>

O exemplo a seguir valida os resultados da consulta usando as opções de linha de comando **--s3-bucket** e **--s3-prefix** para especificar o nome e o prefixo do bucket do S3 que contém os arquivos de resultados de consulta e o arquivo de assinatura.

```
aws cloudtrail verify-query-results --s3-bucket {{amzn-s3-demo-bucket}} --s3-prefix {{prefix}} --region {{region}}
```

O exemplo a seguir valida os resultados da consulta baixados usando a opção de linha de comando **--local-export-path** para especificar o caminho local para os arquivos de resultados de consulta e o arquivo de assinatura. Para obter mais informações sobre como baixar arquivos de resultados de consulta, verifique [Baixe os resultados de sua consulta salva no CloudTrail Lake](view-download-cloudtrail-lake-query-results.md#cloudtrail-download-lake-query-results).

```
aws cloudtrail verify-query-results --local-export-path {{local_file_path}} --region {{region}}
```

#### Resultados da validação
<a name="cloudtrail-query-results-validation-cli-command-messages"></a>

A tabela a seguir descreve as possíveis mensagens de validação de arquivos de resultados de consulta e de assinatura.


****  

| Tipo de arquivo | Mensagem de validação | Description | 
| --- | --- | --- | 
| Sign file | Successfully validated sign and query result files | A assinatura do arquivo de assinatura é válida. Os arquivos de resultados de consulta aos quais ele faz referência podem ser verificados. | 
| Query result file | `ValidationError: "File {{file_name}} has inconsistent hash value with hash value recorded in sign file, hash value in sign file is {{expected_hash}}, but get {{computed_hash}}` | A validação falhou porque o valor de hash do arquivo de resultados de consulta não correspondia ao fileHashValue do arquivo de assinatura. | 
| Sign file | `ValidationError: Invalid signature in sign file` | A validação do arquivo de assinatura falhou porque a assinatura não é válida. | 

## CloudTrail estrutura de arquivo de assinatura
<a name="cloudtrail-results-file-validation-sign-file-structure"></a>

O arquivo de assinatura contém o nome de cada arquivo de resultado de consulta do S3 que foi entregue ao seu bucket do Amazon S3 quando você salvou os resultados de consulta, o valor de hash de cada arquivo de resultado de consulta e a assinatura digital do arquivo. A assinatura digital e os valores de hash são usados para validar a integridade dos arquivos de resultado de consulta e do próprio arquivo de assinatura. 

### Local do arquivo de assinatura
<a name="cloudtrail-results-file-validation-sign-file-location"></a>

O arquivo de assinatura é entregue a um local de bucket do Amazon S3 que segue essa sintaxe.

```
s3://{{amzn-s3-demo-bucket}}/{{optional-prefix/}}AWSLogs/{{aws-account-ID}}/CloudTrail-Lake/Query/{{year}}/{{month}}/{{date}}/{{query-ID}}/result_sign.json
```

### Amostra de conteúdo do arquivo de assinatura
<a name="cloudtrail-results-file-validation-sign-file-contents"></a>

O exemplo de arquivo de sinal a seguir contém informações sobre os resultados da consulta CloudTrail Lake.

```
{
  "version": "1.0",
  "region": "us-east-1",
  "files": [
    {
      "fileHashValue" : "de85a48b8a363033c891abd723181243620a3af3b6505f0a44db77e147e9c188",
      "fileName" : "result_1.csv.gz"
    }
  ],
  "hashAlgorithm" : "SHA-256",
  "signatureAlgorithm" : "SHA256withRSA",
  "queryCompleteTime": "2022-05-10T22:06:30Z",
  "hashSignature" : "7664652aaf1d5a17a12ba50abe6aca77c0ec76264bdf7dce71ac6d1c7781117c2a412e5820bccf473b1361306dff648feae20083ad3a27c6118172a81635829bdc7f7b795ebfabeb5259423b2fb2daa7d1d02f55791efa403dac553171e7ce5f9307d13e92eeec505da41685b4102c71ec5f1089168dacde702c8d39fed2f25e9216be5c49769b9db51037cb70a84b5712e1dffb005a74580c7fdcbb89a16b9b7674e327de4f5414701a772773a4c98eb008cca34228e294169901c735221e34cc643ead34628aabf1ba2c32e0cdf28ef403e8fe3772499ac61e21b70802dfddded9bea0ddfc3a021bf2a0b209f312ccee5a43f2b06aa35cac34638f7611e5d7",
  "publicKeyFingerprint" : "67b9fa73676d86966b449dd677850753"
}
```

### Descrições dos campos do arquivo de assinatura
<a name="cloudtrail-results-file-validation-sign-file-descriptions"></a>

Veja a seguir as descrições de cada campo no arquivo de assinatura: 

`version`  
A versão do arquivo de assinatura. 

`region`  
A região da AWS conta usada para salvar os resultados da consulta. 

`files.fileHashValue`  
O valor de hash com codificação hexadecimal do conteúdo do arquivo de log não compactado.

`files.fileName`  
O nome do arquivo de resultado de consulta. 

`hashAlgorithm`  
O algoritmo de hash usado para fazer hash do arquivo de resultado de consulta. 

`signatureAlgorithm`  
O algoritmo usado para assinar o arquivo. 

`queryCompleteTime`  
Indica quando os resultados da consulta foram CloudTrail entregues ao bucket do S3. Você pode usar esse valor para encontrar a chave pública.

`hashSignature`  
A assinatura de hash do arquivo.

`publicKeyFingerprint`  
A impressão digital com codificação hexadecimal da chave pública usada para assinar o arquivo.

## Implementações personalizadas da validação da integridade do arquivo de resultados da CloudTrail consulta
<a name="cloudtrail-results-file-custom-validation"></a>

Como CloudTrail usa algoritmos criptográficos e funções de hash padrão do setor e disponíveis abertamente, você pode criar suas próprias ferramentas para validar a integridade dos arquivos de resultados da CloudTrail consulta. Quando você salva os resultados da consulta em um bucket do Amazon S3, CloudTrail entrega um arquivo de sinal para o seu bucket do S3. Você pode implementar sua própria solução de validação para validar os arquivos de resultados da assinatura e da consulta. Para obter mais informações sobre o arquivo de assinatura, consulte [CloudTrail estrutura de arquivo de assinatura](#cloudtrail-results-file-validation-sign-file-structure). 

Este tópico descreve como o arquivo de assinatura é assinado e detalha as etapas que você precisará seguir para implementar uma solução que valide o arquivo de assinatura e os arquivos de resultado de consulta aos quais o arquivo de assinatura faz referência. 

### Entendendo como CloudTrail os arquivos de assinatura são assinados
<a name="cloudtrail-results-file-custom-validation-how-cloudtrail-sign-files-are-signed"></a>

CloudTrail os arquivos de assinatura são assinados com assinaturas digitais RSA. Para cada arquivo de sinal, CloudTrail faça o seguinte: 

1. Cria uma lista de hash contendo o valor de hash para cada arquivo de resultado de consulta.

1. Obtém uma chave privada exclusiva para a região.

1. Transmite o hash SHA-256 da string e a chave privada ao algoritmo de assinatura RSA, que produz uma assinatura digital.

1. Codifica o código de byte da assinatura em formato hexadecimal.

1. Coloca a assinatura digital no arquivo de assinatura.

#### Conteúdo da string de assinatura de dados
<a name="cloudtrail-results-file-custom-validation-data-signing-string-summary"></a>

A string de assinatura de dados consiste no valor de hash para cada arquivo de resultado de consulta separado por um espaço. O arquivo de assinatura lista o `fileHashValue` para cada arquivo de resultado de consulta.

### Etapas da implementação da validação personalizada
<a name="cloudtrail-results-file-custom-validation-steps"></a>

Ao implementar uma solução personalizada de validação, você precisará validar o arquivo de assinatura e os arquivos de resultado de consulta aos quais ele faz referência. 

#### Validar o arquivo de assinatura
<a name="cloudtrail-results-file-custom-validation-steps-sign"></a>

Para validar um arquivo de assinatura, você precisa da assinatura dele, da chave pública cuja chave privada foi usada para assiná-lo e de uma string de assinatura de dados computada. 

1. Obtenha o arquivo de assinatura.

1. Verifique se o arquivo de assinatura foi recuperado de seu local original. 

1. Obtenha a assinatura com codificação hexadecimal do arquivo de assinatura.

1. Obtenha a impressão digital com codificação hexadecimal da chave pública cuja chave privada foi usada para assinar o arquivo de assinatura.

1. Recupere a chave pública do intervalo de tempo correspondente a `queryCompleteTime` no arquivo de assinatura. Para o intervalo de tempo, escolha um `StartTime` anterior a `queryCompleteTime` e um `EndTime` posterior a `queryCompleteTime`.

1. Entre as chaves públicas recuperadas, escolha aquela cuja impressão digital corresponda ao valor `publicKeyFingerprint` no arquivo de assinatura.

1. Usando uma lista de hash contendo o valor de hash para cada arquivo de resultado de consulta separado por um espaço, recrie a string de assinatura de dados usada para verificar a assinatura do arquivo de assinatura. O arquivo de assinatura lista o `fileHashValue` para cada arquivo de resultado de consulta.

   Por exemplo, se a matriz `files` do seu arquivo de assinatura contiver os três arquivos de resultados de consulta a seguir, sua lista de hash será “aaa bbb ccc”.

   ```
   “files": [ 
      { 
           "fileHashValue" : “aaa”, 
           "fileName" : "result_1.csv.gz" 
      },
      {       
           "fileHashValue" : “bbb”,       
           "fileName" : "result_2.csv.gz"      
      },
      { 
           "fileHashValue" : “ccc”,       
           "fileName" : "result_3.csv.gz" 
      }
   ],
   ```

1. Para validar a assinatura, transmita o hash SHA-256 da string, a chave pública e a assinatura como parâmetros ao algoritmo de verificação de assinatura RSA. Se o resultado for verdadeiro, o arquivo de assinatura será válido. 

#### Validar os arquivos de resultados de consulta
<a name="cloudtrail-results-file-custom-validation-steps-logs"></a>

Se o arquivo de assinatura for válido, valide os arquivos de resultados de consulta aos quais o arquivo de assinatura faz referência. Para validar a integridade de um arquivo de resultado de consulta, calcule seu valor de hash SHA-256 em seu conteúdo compactado e compare os resultados com o `fileHashValue` do arquivo de resultado de consulta registrado no arquivo de assinatura. Se os hashes forem correspondentes, o arquivo de resultado de consulta será válido.

As seções a seguir descrevem o processo de validação em detalhes.

#### A. Obter o arquivo de assinatura
<a name="cloudtrail-results-file-custom-validation-steps-get-the-sign-file"></a>

Os primeiros passos são obter o arquivo de assinatura e obter a impressão digital da chave pública.

1. Obtenha o arquivo de assinatura do seu bucket do Amazon S3 para os resultados de consulta que deseja validar. 

1. Em seguida, obtenha o valor `hashSignature` do arquivo de assinatura.

1. No arquivo de assinatura, obtenha a impressão digital da chave pública cuja chave privada foi usada para assinar o arquivo do campo `publicKeyFingerprint`. 

#### B. Recuperar a chave pública para validar o arquivo de assinatura
<a name="cloudtrail-results-file-custom-validation-steps-retrieve-public-key"></a>

Para obter a chave pública para validar o arquivo de assinatura, você pode usar a API AWS CLI ou a CloudTrail API. Em ambos os casos, você especifica um intervalo de tempo (ou seja, um horário de início e de término) para o arquivo de assinatura que você deseja validar. Use um intervalo de tempo correspondente a `queryCompleteTime` no arquivo de assinatura. Uma ou mais chaves públicas podem ser retornadas para o período que você especificar. As chaves retornadas podem ter períodos de validade que se sobrepõem.

**nota**  
Como CloudTrail usa pares de private/public chaves diferentes por região, cada arquivo de sinal é assinado com uma chave privada exclusiva para sua região. Portanto, quando você valida um arquivo de assinatura de uma região específica, precisa recuperar a chave pública da mesma região.

##### Use o AWS CLI para recuperar chaves públicas
<a name="cloudtrail-results-file-custom-validation-steps-retrieve-public-key-cli"></a>

Para recuperar uma chave pública para um arquivo de sinal usando o AWS CLI, use o `cloudtrail list-public-keys` comando. O comando tem o formato a seguir: 

 `aws cloudtrail list-public-keys [--start-time <start-time>] [--end-time <end-time>]` 

Os parâmetros de horário de início e de término são carimbos de data e hora UTC opcionais. Se eles não forem especificados, a hora atual será usada, e a chave ou as chaves públicas atualmente ativas serão retornadas.

 **Exemplo de resposta** 

A resposta será uma lista de objetos JSON que representam a chave ou as chaves retornadas: 

##### Use a CloudTrail API para recuperar chaves públicas
<a name="cloudtrail-results-file-custom-validation-steps-retrieve-public-key-api"></a>

Para recuperar uma chave pública para um arquivo de assinatura usando a CloudTrail API, transmita os valores de hora de início e hora de término para a `ListPublicKeys` API. A API `ListPublicKeys` retorna as chaves públicas cujas chaves privadas foram usadas para assinar o arquivo dentro do período especificado. Para cada chave pública, a API também retorna a impressão digital correspondente.

##### `ListPublicKeys`
<a name="cloudtrail-results-file-custom-validation-steps-list-public-keys"></a>

Esta seção descreve os parâmetros de solicitação e os elementos de resposta da API `ListPublicKeys`.

**nota**  
A codificação dos campos binários de `ListPublicKeys` está sujeita a alterações. 

 **Parâmetros de solicitação** 


****  

| Name (Nome) | Description | 
| --- | --- | 
|  StartTime  | Opcionalmente, especifica, em UTC, o início do intervalo de tempo para pesquisar a chave pública para o arquivo de assinatura. CloudTrail Se não StartTime for especificado, a hora atual será usada e a chave pública atual será retornada. <br />Tipo: DateTime  | 
|  EndTime  | Opcionalmente, especifica, em UTC, o final do intervalo de tempo para pesquisar chaves públicas para arquivos de assinatura. CloudTrail Se não EndTime for especificado, a hora atual será usada. <br />Tipo: DateTime  | 

 **Elementos de resposta** 

`PublicKeyList`, um conjunto de `PublicKey` objetos que contém: 


****  

|  |  | 
| --- |--- |
|  Name (Nome)  |  Descrição  | 
|  Value  | O valor de chave pública codificado DER no formato PKCS \#1. <br />Tipo: Blob  | 
|  ValidityStartTime  | O horário de início da validade da chave pública.<br />Tipo: DateTime  | 
|  ValidityEndTime  | O horário de término da validade da chave pública.<br />Tipo: DateTime  | 
|  Fingerprint  | A impressão digital da chave pública. A impressão digital pode ser usada para identificar a chave pública que você precisa usar para validar o arquivo de assinatura.<br />Tipo: string  | 

#### C. Escolha a chave pública a ser usada para a validação
<a name="cloudtrail-results-file-custom-validation-steps-choose-public-key"></a>

Entre as chaves públicas recuperadas por `list-public-keys` ou `ListPublicKeys`, escolha a chave pública cuja impressão digital corresponde à impressão digital gravada no campo `publicKeyFingerprint` do arquivo de assinatura. Essa é a chave pública que você usará para validar o arquivo de assinatura. 

#### D. Recrie a string de assinatura de dados
<a name="cloudtrail-results-file-custom-validation-steps-recreate-data-signing-string"></a>

Agora que você tem a assinatura do arquivo de assinatura e a chave pública associada, precisa calcular a string de assinatura de dados. Depois que você calcular a string de assinatura de dados, terá o necessário para verificar a assinatura.

A string de assinatura de dados consiste no valor de hash para cada arquivo de resultado de consulta separado por um espaço. Depois que você recriar essa string, poderá validar o arquivo de assinatura.

#### E. Validar o arquivo de assinatura
<a name="cloudtrail-results-file-custom-validation-steps-validate-sign-file"></a>

Transmita a string de assinatura de dados recriada, a assinatura digital e a chave pública ao algoritmo de verificação de assinatura RSA. Se o resultado for verdadeiro, a assinatura do arquivo de assinatura será verificada, e o arquivo de assinatura será válido. 

#### F. Validar os arquivos de resultados de consulta
<a name="cloudtrail-results-file-custom-validation-steps-validate-log-files"></a>

Depois que você validar o arquivo de assinatura, poderá validar os arquivos de resultado de consulta aos quais ele faz referência. O arquivo de assinatura contém os hashes SHA-256 dos arquivos de resultado de consulta. Se um dos arquivos de resultados da consulta for modificado após a CloudTrail entrega, os hashes SHA-256 serão alterados e a assinatura do arquivo de assinatura não corresponderá. 

Siga o procedimento abaixo para validar os arquivos de resultados de consulta listados na matriz `files` do arquivo de assinatura.

1. Recupere o hash original do arquivo no campo `files.fileHashValue` do arquivo de assinatura.

1. Faça o hash do conteúdo compactado do arquivo de resultado de consulta com o algoritmo de hashing especificado em `hashAlgorithm`.

1. Compare o valor de hash que você gerou para cada arquivo de resultado de consulta com o `files.fileHashValue` do arquivo de assinatura. Se os hashes forem correspondentes, os arquivos de resultado de consulta serão válidos.

### Validação offline de arquivos de resultado de consulta e assinatura
<a name="cloudtrail-results-file-custom-validation-offline"></a>

Ao validar offline os arquivos de resultado de consulta e assinatura, você pode seguir os procedimentos descritos nas seções anteriores. No entanto, você deve levar em consideração as seguintes informações sobre chaves públicas.

#### Chaves públicas
<a name="cloudtrail-results-file-custom-validation-offline-public-keys"></a>

Para fazer a validação offline, primeiramente é necessário obter online (p. ex., chamando `ListPublicKeys`) a chave pública de que você precisa para validar os arquivos de resultado de consulta em um determinado intervalo de tempo e, depois, armazená-la offline. Essa etapa precisará ser repetida sempre que você quiser validar arquivos adicionais fora do período inicial que especificou.

### Exemplo de snippet de validação
<a name="cloudtrail-results-file-custom-validation-sample-code"></a>

O trecho de amostra a seguir fornece um código básico para validar arquivos de resultados de CloudTrail assinatura e consulta. O código básico é online/offline agnóstico; ou seja, cabe a você decidir se deseja implementá-lo com ou sem conectividade on-line com. AWS A implementação sugerida usa [Java Cryptography Extension (JCE)](https://en.wikipedia.org/wiki/Java_Cryptography_Extension) e [Bouncy Castle](https://www.bouncycastle.org/) como um provedor de segurança. 

O exemplo de snippet mostra:
+ Como criar a string de assinatura de dados usada para validar a assinatura do arquivo de assinatura.
+ Como verificar a assinatura do arquivo de assinatura.
+ Como calcular o valor de hash para o arquivo de resultado de consulta e compará-lo com o `fileHashValue` listado no arquivo de assinatura para verificar a autenticidade do arquivo de resultado de consulta.

```
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.RSAPublicKey;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.json.JSONArray;
import org.json.JSONObject;
 
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
 
 
public class SignFileValidationSampleCode {
 
    public void validateSignFile(String s3Bucket, String s3PrefixPath) throws Exception {
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
 
        // Load the sign file from S3 (using Amazon S3 Client) or from your local copy
        JSONObject signFile = loadSignFileToMemory(s3Bucket, String.format("%s/%s", s3PrefixPath, "result_sign.json"));
 
        // Using the Bouncy Castle provider as a JCE security provider - http://www.bouncycastle.org/
        Security.addProvider(new BouncyCastleProvider());
 
        List<String> hashList = new ArrayList<>();
 
        JSONArray jsonArray = signFile.getJSONArray("files");
 
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject file = jsonArray.getJSONObject(i);
            String fileS3ObjectKey = String.format("%s/%s", s3PrefixPath, file.getString("fileName"));
 
            // Load the export file from S3 (using Amazon S3 Client) or from your local copy
            byte[] exportFileContent = loadCompressedExportFileInMemory(s3Bucket, fileS3ObjectKey);
            messageDigest.update(exportFileContent);
            byte[] exportFileHash = messageDigest.digest();
            messageDigest.reset();
            byte[] expectedHash = Hex.decodeHex(file.getString("fileHashValue"));
 
            boolean signaturesMatch = Arrays.equals(expectedHash, exportFileHash);
            if (!signaturesMatch) {
                System.err.println(String.format("Export file: %s/%s hash doesn't match.\tExpected: %s Actual: %s",
                        s3Bucket, fileS3ObjectKey,
                        Hex.encodeHexString(expectedHash), Hex.encodeHexString(exportFileHash)));
            } else {
                System.out.println(String.format("Export file: %s/%s hash match",
                        s3Bucket, fileS3ObjectKey));
            }
 
            hashList.add(file.getString("fileHashValue"));
        }
        String hashListString = hashList.stream().collect(Collectors.joining(" "));
 
        /*
            NOTE:
            To find the right public key to verify the signature, call CloudTrail ListPublicKey API to get a list
            of public keys, then match by the publicKeyFingerprint in the sign file. Also, the public key bytes
            returned from ListPublicKey API are DER encoded in PKCS#1 format:
 
            PublicKeyInfo ::= SEQUENCE {
                algorithm       AlgorithmIdentifier,
                PublicKey       BIT STRING
            }
 
            AlgorithmIdentifier ::= SEQUENCE {
                algorithm       OBJECT IDENTIFIER,
                parameters      ANY DEFINED BY algorithm OPTIONAL
            }
        */
        byte[] pkcs1PublicKeyBytes = getPublicKey(signFile.getString("queryCompleteTime"),
                signFile.getString("publicKeyFingerprint"));
        byte[] signatureContent = Hex.decodeHex(signFile.getString("hashSignature"));
 
        // Transform the PKCS#1 formatted public key to x.509 format.
        RSAPublicKey rsaPublicKey = RSAPublicKey.getInstance(pkcs1PublicKeyBytes);
        AlgorithmIdentifier rsaEncryption = new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, null);
        SubjectPublicKeyInfo publicKeyInfo = new SubjectPublicKeyInfo(rsaEncryption, rsaPublicKey);
 
        // Create the PublicKey object needed for the signature validation
        PublicKey publicKey = KeyFactory.getInstance("RSA", "BC")
                .generatePublic(new X509EncodedKeySpec(publicKeyInfo.getEncoded()));
 
        // Verify signature
        Signature signature = Signature.getInstance("SHA256withRSA", "BC");
        signature.initVerify(publicKey);
        signature.update(hashListString.getBytes("UTF-8"));
 
        if (signature.verify(signatureContent)) {
            System.out.println("Sign file signature is valid.");
        } else {
            System.err.println("Sign file signature failed validation.");
        }
 
        System.out.println("Sign file validation completed.");
    }
}
```