SIGN IN SIGN UP

Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below.

0 0 0 Java
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// snippet-start:[cloudtrail.java.log-and-digest-file-validation.complete]
import java.util.Arrays;
import java.security.MessageDigest;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import org.json.JSONObject;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.apache.commons.codec.binary.Hex;
public class DigestFileValidator {
public void validateDigestFile(String digestS3Bucket, String digestS3Object, String digestSignature) {
// Using the Bouncy Castle provider as a JCE security provider - http://www.bouncycastle.org/
Security.addProvider(new BouncyCastleProvider());
// Load the digest file from S3 (using Amazon S3 Client) or from your local copy
JSONObject digestFile = loadDigestFileInMemory(digestS3Bucket, digestS3Object);
// Check that the digest file has been retrieved from its original location
if (!digestFile.getString("digestS3Bucket").equals(digestS3Bucket) ||
!digestFile.getString("digestS3Object").equals(digestS3Object)) {
System.err.println("Digest file has been moved from its original location.");
} else {
// Compute digest file hash
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(convertToByteArray(digestFile));
byte[] digestFileHash = messageDigest.digest();
messageDigest.reset();
// Compute the data to sign
String dataToSign = String.format("%s%n%s/%s%n%s%n%s",
digestFile.getString("digestEndTime"),
digestFile.getString("digestS3Bucket"), digestFile.getString("digestS3Object"), // Constructing the S3 path of the digest file as part of the data to sign
Hex.encodeHexString(digestFileHash),
digestFile.getString("previousDigestSignature"));
byte[] signatureContent = Hex.decodeHex(digestSignature);
/*
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 digest 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
}
*/
pkcs1PublicKeyBytes = getPublicKey(digestFile.getString("digestPublicKeyFingerprint")));
// 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(dataToSign.getBytes("UTF-8"));
if (signature.verify(signatureContent)) {
System.out.println("Digest file signature is valid, validating log files…");
for (int i = 0; i < digestFile.getJSONArray("logFiles").length(); i++) {
JSONObject logFileMetadata = digestFile.getJSONArray("logFiles").getJSONObject(i);
// Compute log file hash
byte[] logFileContent = loadUncompressedLogFileInMemory(
logFileMetadata.getString("s3Bucket"),
logFileMetadata.getString("s3Object")
);
messageDigest.update(logFileContent);
byte[] logFileHash = messageDigest.digest();
messageDigest.reset();
// Retrieve expected hash for the log file being processed
byte[] expectedHash = Hex.decodeHex(logFileMetadata.getString("hashValue"));
boolean signaturesMatch = Arrays.equals(expectedHash, logFileHash);
if (!signaturesMatch) {
System.err.println(String.format("Log file: %s/%s hash doesn't match.\tExpected: %s Actual: %s",
logFileMetadata.getString("s3Bucket"), logFileMetadata.getString("s3Object"),
Hex.encodeHexString(expectedHash), Hex.encodeHexString(logFileHash)));
} else {
System.out.println(String.format("Log file: %s/%s hash match",
logFileMetadata.getString("s3Bucket"), logFileMetadata.getString("s3Object")));
}
}
} else {
System.err.println("Digest signature failed validation.");
}
System.out.println("Digest file validation completed.");
if (chainValidationIsEnabled()) {
// This enables the digests' chain validation
validateDigestFile(
digestFile.getString("previousDigestS3Bucket"),
digestFile.getString("previousDigestS3Object"),
digestFile.getString("previousDigestSignature"));
}
}
}
}
// snippet-end:[cloudtrail.java.log-and-digest-file-validation.complete]