In-Toto Attestations in Java

Cmprehensive Supply Chain Security with In-Toto Attestations

In-Toto provides a framework to secure software supply chains by cryptographically attesting to each step. This article covers comprehensive In-Toto attestation generation, verification, and management in Java with advanced features like policy enforcement, SLSA compliance, and automated provenance.

Core In-Toto Implementation

package com.titliel.intoto;
import java.io.*;
import java.nio.file.*;
import java.security.*;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
/**
* Titliel In-Toto Attestation Framework
* Comprehensive supply chain security with SLSA compliance
*/
public class TitlielInToto {
private final InTotoConfig config;
private final KeyManager keyManager;
private final AttestationGenerator attestationGenerator;
private final AttestationVerifier attestationVerifier;
private final PolicyEngine policyEngine;
private final ObjectMapper objectMapper;
public TitlielInToto() {
this.config = InTotoConfig.getInstance();
this.keyManager = new KeyManager();
this.attestationGenerator = new AttestationGenerator();
this.attestationVerifier = new AttestationVerifier();
this.policyEngine = new PolicyEngine();
this.objectMapper = new ObjectMapper()
.configure(SerializationFeature.INDENT_OUTPUT, true)
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
initialize();
}
private void initialize() {
try {
// Initialize key management
keyManager.initialize();
// Load policies
policyEngine.loadPolicies();
SecurityLogger.info("Titliel In-Toto framework initialized successfully");
} catch (Exception e) {
SecurityLogger.error("Failed to initialize In-Toto framework", e);
throw new InTotoException("Initialization failed", e);
}
}
/**
* Generate comprehensive attestation for a build step
*/
public AttestationResult generateAttestation(BuildContext context) {
long startTime = System.currentTimeMillis();
AttestationResult result = new AttestationResult(context);
try {
// Validate build context
validateBuildContext(context);
// Generate step attestation
StepAttestation stepAttestation = generateStepAttestation(context);
// Generate material attestation
MaterialAttestation materialAttestation = generateMaterialAttestation(context);
// Generate product attestation
ProductAttestation productAttestation = generateProductAttestation(context);
// Generate provenance attestation
ProvenanceAttestation provenance = generateProvenanceAttestation(
context, stepAttestation, materialAttestation, productAttestation);
// Generate link metadata
LinkMetadata link = generateLinkMetadata(context, provenance);
// Sign the attestation
SignedAttestation signedAttestation = signAttestation(link);
// Verify the attestation
VerificationResult verification = verifyAttestation(signedAttestation);
// Check policy compliance
PolicyCompliance compliance = checkPolicyCompliance(signedAttestation, context);
// Build result
result.setStepAttestation(stepAttestation);
result.setMaterialAttestation(materialAttestation);
result.setProductAttestation(productAttestation);
result.setProvenanceAttestation(provenance);
result.setLinkMetadata(link);
result.setSignedAttestation(signedAttestation);
result.setVerificationResult(verification);
result.setPolicyCompliance(compliance);
result.setSuccess(true);
// Store attestation
storeAttestation(signedAttestation, context);
SecurityLogger.info("Attestation generated successfully for build: {}", 
context.getBuildId());
} catch (Exception e) {
result.setSuccess(false);
result.setError(e.getMessage());
SecurityLogger.error("Failed to generate attestation", e);
} finally {
result.setGenerationTime(System.currentTimeMillis() - startTime);
}
return result;
}
/**
* Generate step attestation
*/
private StepAttestation generateStepAttestation(BuildContext context) {
StepAttestation attestation = new StepAttestation();
attestation.setStepName(context.getStepName());
attestation.setStepType(context.getStepType());
attestation.setCommand(context.getCommand());
attestation.setEnvironment(context.getEnvironment());
attestation.setWorkingDir(context.getWorkingDirectory());
attestation.setStartTime(Instant.now());
attestation.setEndTime(Instant.now()); // Will be updated
// Capture environment details
attestation.setEnvVars(System.getenv());
attestation.setSystemProperties(System.getProperties());
// Capture runtime information
attestation.setJavaVersion(System.getProperty("java.version"));
attestation.setOsName(System.getProperty("os.name"));
attestation.setOsVersion(System.getProperty("os.version"));
// Capture user information
attestation.setUsername(System.getProperty("user.name"));
attestation.setUserHome(System.getProperty("user.home"));
return attestation;
}
/**
* Generate material attestation
*/
private MaterialAttestation generateMaterialAttestation(BuildContext context) {
MaterialAttestation attestation = new MaterialAttestation();
for (Path material : context.getMaterials()) {
try {
MaterialInfo materialInfo = createMaterialInfo(material);
attestation.addMaterial(material, materialInfo);
} catch (IOException e) {
SecurityLogger.warn("Failed to process material: {}", material, e);
attestation.addError(material, e.getMessage());
}
}
return attestation;
}
/**
* Create material information with cryptographic hashes
*/
private MaterialInfo createMaterialInfo(Path material) throws IOException {
MaterialInfo info = new MaterialInfo();
// Basic file information
info.setPath(material.toString());
info.setSize(Files.size(material));
info.setLastModified(Files.getLastModifiedTime(material).toMillis());
// Calculate cryptographic hashes
byte[] content = Files.readAllBytes(material);
for (String algorithm : config.getHashAlgorithms()) {
String hash = calculateHash(content, algorithm);
info.addHash(algorithm, hash);
}
// Additional metadata
if (Files.isSymbolicLink(material)) {
info.setSymlinkTarget(Files.readSymbolicLink(material).toString());
}
info.setPermissions(getFilePermissions(material));
info.setOwner(getFileOwner(material));
return info;
}
/**
* Generate product attestation
*/
private ProductAttestation generateProductAttestation(BuildContext context) {
ProductAttestation attestation = new ProductAttestation();
for (Path product : context.getProducts()) {
try {
ProductInfo productInfo = createProductInfo(product);
attestation.addProduct(product, productInfo);
} catch (IOException e) {
SecurityLogger.warn("Failed to process product: {}", product, e);
attestation.addError(product, e.getMessage());
}
}
return attestation;
}
/**
* Create product information
*/
private ProductInfo createProductInfo(Path product) throws IOException {
ProductInfo info = new ProductInfo();
// Basic file information
info.setPath(product.toString());
info.setSize(Files.size(product));
info.setLastModified(Files.getLastModifiedTime(product).toMillis());
// Calculate cryptographic hashes
byte[] content = Files.readAllBytes(product);
for (String algorithm : config.getHashAlgorithms()) {
String hash = calculateHash(content, algorithm);
info.addHash(algorithm, hash);
}
// Additional metadata
info.setPermissions(getFilePermissions(product));
info.setOwner(getFileOwner(product));
// Generate artifact URI
info.setArtifactUri(generateArtifactUri(product));
return info;
}
/**
* Generate provenance attestation
*/
private ProvenanceAttestation generateProvenanceAttestation(BuildContext context,
StepAttestation step,
MaterialAttestation materials,
ProductAttestation products) {
ProvenanceAttestation provenance = new ProvenanceAttestation();
provenance.setBuildId(context.getBuildId());
provenance.setBuildType(context.getBuildType());
provenance.setBuilder(context.getBuilder());
provenance.setInvocationId(context.getInvocationId());
provenance.setStartedAt(step.getStartTime());
provenance.setFinishedAt(Instant.now());
// Build configuration
provenance.setBuildConfig(context.getBuildConfig());
// Materials and products
provenance.setMaterials(materials.getMaterials());
provenance.setProducts(products.getProducts());
// Build steps
provenance.setSteps(context.getBuildSteps());
// Metadata
provenance.setMetadata(createProvenanceMetadata(context));
// SLSA compliance
provenance.setSlsaLevel(calculateSlsaLevel(context, materials, products));
return provenance;
}
/**
* Generate link metadata (in-toto link format)
*/
private LinkMetadata generateLinkMetadata(BuildContext context,
ProvenanceAttestation provenance) {
LinkMetadata link = new LinkMetadata();
link.setName(context.getStepName());
link.setMaterials(provenance.getMaterials());
link.setProducts(provenance.getProducts());
link.setByProducts(collectByProducts(context));
link.setCommand(context.getCommand());
link.setEnvironment(context.getEnvironment());
link.setWorkingDir(context.getWorkingDirectory());
return link;
}
/**
* Sign the attestation
*/
private SignedAttestation signAttestation(LinkMetadata link) {
try {
// Serialize link metadata
String json = objectMapper.writeValueAsString(link);
byte[] data = json.getBytes();
// Sign with private key
Signature signature = keyManager.sign(data);
// Create signed attestation
SignedAttestation signed = new SignedAttestation();
signed.setLinkMetadata(link);
signed.setSignature(signature);
signed.setKeyId(keyManager.getKeyId());
signed.setSigningTime(Instant.now());
return signed;
} catch (Exception e) {
throw new InTotoException("Failed to sign attestation", e);
}
}
/**
* Verify attestation signature and integrity
*/
private VerificationResult verifyAttestation(SignedAttestation attestation) {
VerificationResult result = new VerificationResult();
try {
// Verify signature
boolean signatureValid = keyManager.verify(
attestation.getLinkMetadata(),
attestation.getSignature()
);
result.setSignatureValid(signatureValid);
// Verify link integrity
result.setLinkIntegrity(verifyLinkIntegrity(attestation.getLinkMetadata()));
// Verify material-product relationships
result.setMaterialProductConsistency(
verifyMaterialProductConsistency(attestation.getLinkMetadata()));
// Calculate overall verification score
result.calculateScore();
} catch (Exception e) {
result.setError(e.getMessage());
SecurityLogger.error("Attestation verification failed", e);
}
return result;
}
/**
* Check policy compliance
*/
private PolicyCompliance checkPolicyCompliance(SignedAttestation attestation,
BuildContext context) {
return policyEngine.evaluateCompliance(attestation, context);
}
/**
* Store attestation for later verification
*/
private void storeAttestation(SignedAttestation attestation, BuildContext context) {
try {
// Create attestation directory
Path attestationDir = getAttestationDirectory(context);
Files.createDirectories(attestationDir);
// Generate filename
String filename = String.format("%s-%s.json",
context.getBuildId(),
Instant.now().toString().replace(":", "-"));
Path attestationFile = attestationDir.resolve(filename);
// Write attestation
objectMapper.writeValue(attestationFile.toFile(), attestation);
// Generate accompanying metadata
storeAttestationMetadata(attestation, context, attestationFile);
SecurityLogger.info("Attestation stored at: {}", attestationFile);
} catch (Exception e) {
SecurityLogger.error("Failed to store attestation", e);
}
}
/**
* Verify a complete supply chain
*/
public SupplyChainVerification verifySupplyChain(List<SignedAttestation> attestations,
SupplyChainPolicy policy) {
SupplyChainVerification result = new SupplyChainVerification();
try {
// Verify individual attestations
for (SignedAttestation attestation : attestations) {
VerificationResult verification = verifyAttestation(attestation);
result.addVerificationResult(attestation, verification);
}
// Verify chain continuity
result.setChainContinuity(verifyChainContinuity(attestations));
// Verify policy compliance across chain
result.setPolicyCompliance(verifyChainPolicyCompliance(attestations, policy));
// Calculate overall chain integrity
result.calculateChainIntegrity();
} catch (Exception e) {
result.setError(e.getMessage());
SecurityLogger.error("Supply chain verification failed", e);
}
return result;
}
/**
* Generate SLSA provenance statement
*/
public SLSAProvenance generateSlsaProvenance(BuildContext context) {
SLSAProvenance provenance = new SLSAProvenance();
provenance.setBuilder(context.getBuilder());
provenance.setBuildType(context.getBuildType());
provenance.setInvocation(context.getBuildInvocation());
provenance.setBuildConfig(context.getBuildConfig());
provenance.setMetadata(context.getBuildMetadata());
provenance.setMaterials(context.getMaterials().stream()
.map(this::createSlsaMaterial)
.collect(Collectors.toList()));
provenance.setProducts(context.getProducts().stream()
.map(this::createSlsaProduct)
.collect(Collectors.toList()));
return provenance;
}
/**
* Verify SLSA provenance
*/
public SLSAVerification verifySlsaProvenance(SLSAProvenance provenance,
SLSAPolicy policy) {
SLSAVerification result = new SLSAVerification();
try {
// Verify builder identity
result.setBuilderVerified(verifyBuilderIdentity(provenance.getBuilder()));
// Verify build invocation
result.setInvocationVerified(verifyBuildInvocation(provenance.getInvocation()));
// Verify materials
result.setMaterialsVerified(verifyMaterials(provenance.getMaterials()));
// Verify products
result.setProductsVerified(verifyProducts(provenance.getProducts()));
// Check SLSA level
result.setSlsaLevel(calculateSlsaCompliance(provenance, policy));
} catch (Exception e) {
result.setError(e.getMessage());
}
return result;
}
// Utility methods
private void validateBuildContext(BuildContext context) {
List<String> errors = new ArrayList<>();
if (context.getBuildId() == null || context.getBuildId().isEmpty()) {
errors.add("Build ID is required");
}
if (context.getStepName() == null || context.getStepName().isEmpty()) {
errors.add("Step name is required");
}
if (context.getMaterials().isEmpty()) {
errors.add("At least one material is required");
}
if (context.getProducts().isEmpty()) {
errors.add("At least one product is required");
}
if (!errors.isEmpty()) {
throw new InTotoException("Invalid build context: " + String.join(", ", errors));
}
}
private String calculateHash(byte[] data, String algorithm) {
try {
MessageDigest digest = MessageDigest.getInstance(algorithm);
byte[] hash = digest.digest(data);
return bytesToHex(hash);
} catch (NoSuchAlgorithmException e) {
throw new InTotoException("Unsupported hash algorithm: " + algorithm, e);
}
}
private String bytesToHex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02x", b));
}
return result.toString();
}
private String getFilePermissions(Path path) {
try {
return PosixFilePermissions.toString(Files.getPosixFilePermissions(path));
} catch (Exception e) {
return "unknown";
}
}
private String getFileOwner(Path path) {
try {
return Files.getOwner(path).getName();
} catch (Exception e) {
return "unknown";
}
}
private String generateArtifactUri(Path product) {
// Generate artifact URI based on configuration
String baseUri = config.getArtifactBaseUri();
String relativePath = product.toString().replace(config.getBuildDirectory(), "");
return baseUri + relativePath;
}
private Map<String, Object> createProvenanceMetadata(BuildContext context) {
Map<String, Object> metadata = new HashMap<>();
metadata.put("generatedAt", Instant.now().toString());
metadata.put("generator", "Titliel-InToto-Java");
metadata.put("version", "1.0.0");
metadata.put("buildTool", context.getBuildTool());
metadata.put("buildSystem", context.getBuildSystem());
return metadata;
}
private SLSALevel calculateSlsaLevel(BuildContext context,
MaterialAttestation materials,
ProductAttestation products) {
// Implement SLSA level calculation based on requirements
// This is a simplified implementation
boolean hasProvenance = true;
boolean hasHermeticBuild = context.isHermetic();
boolean hasReproducibleBuild = context.isReproducible();
boolean hasIsolatedBuild = context.isIsolated();
if (hasIsolatedBuild && hasReproducibleBuild && hasHermeticBuild) {
return SLSALevel.LEVEL_4;
} else if (hasHermeticBuild && hasReproducibleBuild) {
return SLSALevel.LEVEL_3;
} else if (hasProvenance) {
return SLSALevel.LEVEL_2;
} else {
return SLSALevel.LEVEL_1;
}
}
private Map<String, Object> collectByProducts(BuildContext context) {
Map<String, Object> byProducts = new HashMap<>();
// Capture stdout/stderr if available
if (context.getStdout() != null) {
byProducts.put("stdout", context.getStdout());
}
if (context.getStderr() != null) {
byProducts.put("stderr", context.getStderr());
}
// Capture return code
byProducts.put("return-value", context.getReturnCode());
return byProducts;
}
private Path getAttestationDirectory(BuildContext context) {
return Paths.get(config.getAttestationStore(),
context.getBuildId(),
context.getStepName());
}
private void storeAttestationMetadata(SignedAttestation attestation,
BuildContext context,
Path attestationFile) throws IOException {
AttestationMetadata metadata = new AttestationMetadata();
metadata.setBuildId(context.getBuildId());
metadata.setStepName(context.getStepName());
metadata.setAttestationFile(attestationFile.toString());
metadata.setGeneratedAt(Instant.now());
metadata.setSignatureKeyId(attestation.getKeyId());
Path metadataFile = attestationFile.getParent()
.resolve(attestationFile.getFileName() + ".metadata.json");
objectMapper.writeValue(metadataFile.toFile(), metadata);
}
private boolean verifyLinkIntegrity(LinkMetadata link) {
// Verify that materials and products actually exist
// and match their hashes
return true; // Implementation depends on actual verification logic
}
private boolean verifyMaterialProductConsistency(LinkMetadata link) {
// Verify that all materials were consumed
// and all products were produced
return true; // Implementation depends on actual verification logic
}
private boolean verifyChainContinuity(List<SignedAttestation> attestations) {
// Verify that each step's products become the next step's materials
if (attestations.size() < 2) return true;
for (int i = 0; i < attestations.size() - 1; i++) {
SignedAttestation current = attestations.get(i);
SignedAttestation next = attestations.get(i + 1);
// Check product-material continuity
if (!verifyStepContinuity(current, next)) {
return false;
}
}
return true;
}
private boolean verifyStepContinuity(SignedAttestation current, SignedAttestation next) {
// Verify that next step's materials include current step's products
// This is a simplified check
return true;
}
private PolicyCompliance verifyChainPolicyCompliance(List<SignedAttestation> attestations,
SupplyChainPolicy policy) {
PolicyCompliance compliance = new PolicyCompliance();
for (SignedAttestation attestation : attestations) {
// Check each attestation against policy
// This would involve checking step types, commands, environments, etc.
}
return compliance;
}
private SLSAProvenance.Material createSlsaMaterial(Path material) {
SLSAProvenance.Material slsaMaterial = new SLSAProvenance.Material();
try {
byte[] content = Files.readAllBytes(material);
String hash = calculateHash(content, "sha256");
slsaMaterial.setUri(generateArtifactUri(material));
slsaMaterial.setDigest(Map.of("sha256", hash));
} catch (IOException e) {
SecurityLogger.warn("Failed to create SLSA material for: {}", material, e);
}
return slsaMaterial;
}
private SLSAProvenance.Product createSlsaProduct(Path product) {
SLSAProvenance.Product slsaProduct = new SLSAProvenance.Product();
try {
byte[] content = Files.readAllBytes(product);
String hash = calculateHash(content, "sha256");
slsaProduct.setUri(generateArtifactUri(product));
slsaProduct.setDigest(Map.of("sha256", hash));
} catch (IOException e) {
SecurityLogger.warn("Failed to create SLSA product for: {}", product, e);
}
return slsaProduct;
}
private boolean verifyBuilderIdentity(SLSAProvenance.Builder builder) {
// Verify builder identity against trusted builders
return config.getTrustedBuilders().contains(builder.getId());
}
private boolean verifyBuildInvocation(SLSAProvenance.Invocation invocation) {
// Verify build invocation parameters
return true; // Implementation depends on policy
}
private boolean verifyMaterials(List<SLSAProvenance.Material> materials) {
// Verify all materials are from trusted sources
return materials.stream().allMatch(this::isTrustedMaterial);
}
private boolean verifyProducts(List<SLSAProvenance.Product> products) {
// Verify all products have valid signatures/hashes
return products.stream().allMatch(this::hasValidDigest);
}
private SLSALevel calculateSlsaCompliance(SLSAProvenance provenance, SLSAPolicy policy) {
// Calculate SLSA compliance level based on policy
return SLSALevel.LEVEL_3; // Simplified
}
private boolean isTrustedMaterial(SLSAProvenance.Material material) {
// Check if material URI is from trusted source
return material.getUri().startsWith(config.getTrustedSourcePrefix());
}
private boolean hasValidDigest(SLSAProvenance.Product product) {
// Verify product digest is present and valid
return product.getDigest() != null && !product.getDigest().isEmpty();
}
}

Data Models and Attestation Structures

package com.titliel.intoto;
import java.nio.file.Path;
import java.time.Instant;
import java.util.*;
/**
* Build context for attestation generation
*/
public class BuildContext {
private String buildId;
private String stepName;
private StepType stepType;
private List<Path> materials;
private List<Path> products;
private String command;
private Map<String, String> environment;
private Path workingDirectory;
private String buildType;
private String builder;
private String invocationId;
private Map<String, Object> buildConfig;
private List<BuildStep> buildSteps;
private Map<String, Object> buildMetadata;
private String stdout;
private String stderr;
private int returnCode;
private boolean hermetic;
private boolean reproducible;
private boolean isolated;
private String buildTool;
private String buildSystem;
// Getters and setters
public String getBuildId() { return buildId; }
public void setBuildId(String buildId) { this.buildId = buildId; }
public String getStepName() { return stepName; }
public void setStepName(String stepName) { this.stepName = stepName; }
public StepType getStepType() { return stepType; }
public void setStepType(StepType stepType) { this.stepType = stepType; }
public List<Path> getMaterials() { return materials; }
public void setMaterials(List<Path> materials) { this.materials = materials; }
public List<Path> getProducts() { return products; }
public void setProducts(List<Path> products) { this.products = products; }
public String getCommand() { return command; }
public void setCommand(String command) { this.command = command; }
public Map<String, String> getEnvironment() { return environment; }
public void setEnvironment(Map<String, String> environment) { this.environment = environment; }
public Path getWorkingDirectory() { return workingDirectory; }
public void setWorkingDirectory(Path workingDirectory) { this.workingDirectory = workingDirectory; }
public String getBuildType() { return buildType; }
public void setBuildType(String buildType) { this.buildType = buildType; }
public String getBuilder() { return builder; }
public void setBuilder(String builder) { this.builder = builder; }
public String getInvocationId() { return invocationId; }
public void setInvocationId(String invocationId) { this.invocationId = invocationId; }
public Map<String, Object> getBuildConfig() { return buildConfig; }
public void setBuildConfig(Map<String, Object> buildConfig) { this.buildConfig = buildConfig; }
public List<BuildStep> getBuildSteps() { return buildSteps; }
public void setBuildSteps(List<BuildStep> buildSteps) { this.buildSteps = buildSteps; }
public Map<String, Object> getBuildMetadata() { return buildMetadata; }
public void setBuildMetadata(Map<String, Object> buildMetadata) { this.buildMetadata = buildMetadata; }
public String getStdout() { return stdout; }
public void setStdout(String stdout) { this.stdout = stdout; }
public String getStderr() { return stderr; }
public void setStderr(String stderr) { this.stderr = stderr; }
public int getReturnCode() { return returnCode; }
public void setReturnCode(int returnCode) { this.returnCode = returnCode; }
public boolean isHermetic() { return hermetic; }
public void setHermetic(boolean hermetic) { this.hermetic = hermetic; }
public boolean isReproducible() { return reproducible; }
public void setReproducible(boolean reproducible) { this.reproducible = reproducible; }
public boolean isIsolated() { return isolated; }
public void setIsolated(boolean isolated) { this.isolated = isolated; }
public String getBuildTool() { return buildTool; }
public void setBuildTool(String buildTool) { this.buildTool = buildTool; }
public String getBuildSystem() { return buildSystem; }
public void setBuildSystem(String buildSystem) { this.buildSystem = buildSystem; }
}
/**
* Step types in supply chain
*/
public enum StepType {
FETCH,
BUILD,
TEST,
PACKAGE,
SIGN,
DEPLOY,
VERIFY,
CUSTOM
}
/**
* Build step information
*/
public class BuildStep {
private String name;
private String type;
private String command;
private Map<String, String> environment;
private Instant startTime;
private Instant endTime;
// Getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getCommand() { return command; }
public void setCommand(String command) { this.command = command; }
public Map<String, String> getEnvironment() { return environment; }
public void setEnvironment(Map<String, String> environment) { this.environment = environment; }
public Instant getStartTime() { return startTime; }
public void setStartTime(Instant startTime) { this.startTime = startTime; }
public Instant getEndTime() { return endTime; }
public void setEndTime(Instant endTime) { this.endTime = endTime; }
}
/**
* Step attestation
*/
public class StepAttestation {
private String stepName;
private StepType stepType;
private String command;
private Map<String, String> environment;
private Path workingDir;
private Instant startTime;
private Instant endTime;
private Map<String, String> envVars;
private Properties systemProperties;
private String javaVersion;
private String osName;
private String osVersion;
private String username;
private String userHome;
// Getters and setters
public String getStepName() { return stepName; }
public void setStepName(String stepName) { this.stepName = stepName; }
public StepType getStepType() { return stepType; }
public void setStepType(StepType stepType) { this.stepType = stepType; }
public String getCommand() { return command; }
public void setCommand(String command) { this.command = command; }
public Map<String, String> getEnvironment() { return environment; }
public void setEnvironment(Map<String, String> environment) { this.environment = environment; }
public Path getWorkingDir() { return workingDir; }
public void setWorkingDir(Path workingDir) { this.workingDir = workingDir; }
public Instant getStartTime() { return startTime; }
public void setStartTime(Instant startTime) { this.startTime = startTime; }
public Instant getEndTime() { return endTime; }
public void setEndTime(Instant endTime) { this.endTime = endTime; }
public Map<String, String> getEnvVars() { return envVars; }
public void setEnvVars(Map<String, String> envVars) { this.envVars = envVars; }
public Properties getSystemProperties() { return systemProperties; }
public void setSystemProperties(Properties systemProperties) { this.systemProperties = systemProperties; }
public String getJavaVersion() { return javaVersion; }
public void setJavaVersion(String javaVersion) { this.javaVersion = javaVersion; }
public String getOsName() { return osName; }
public void setOsName(String osName) { this.osName = osName; }
public String getOsVersion() { return osVersion; }
public void setOsVersion(String osVersion) { this.osName = osVersion; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getUserHome() { return userHome; }
public void setUserHome(String userHome) { this.userHome = userHome; }
}
/**
* Material attestation
*/
public class MaterialAttestation {
private final Map<Path, MaterialInfo> materials;
private final Map<Path, String> errors;
public MaterialAttestation() {
this.materials = new HashMap<>();
this.errors = new HashMap<>();
}
public void addMaterial(Path path, MaterialInfo info) {
materials.put(path, info);
}
public void addError(Path path, String error) {
errors.put(path, error);
}
// Getters
public Map<Path, MaterialInfo> getMaterials() { return Collections.unmodifiableMap(materials); }
public Map<Path, String> getErrors() { return Collections.unmodifiableMap(errors); }
public boolean hasErrors() { return !errors.isEmpty(); }
}
/**
* Material information
*/
public class MaterialInfo {
private String path;
private long size;
private long lastModified;
private Map<String, String> hashes;
private String symlinkTarget;
private String permissions;
private String owner;
public MaterialInfo() {
this.hashes = new HashMap<>();
}
// Getters and setters
public String getPath() { return path; }
public void setPath(String path) { this.path = path; }
public long getSize() { return size; }
public void setSize(long size) { this.size = size; }
public long getLastModified() { return lastModified; }
public void setLastModified(long lastModified) { this.lastModified = lastModified; }
public Map<String, String> getHashes() { return Collections.unmodifiableMap(hashes); }
public void addHash(String algorithm, String hash) { hashes.put(algorithm, hash); }
public String getSymlinkTarget() { return symlinkTarget; }
public void setSymlinkTarget(String symlinkTarget) { this.symlinkTarget = symlinkTarget; }
public String getPermissions() { return permissions; }
public void setPermissions(String permissions) { this.permissions = permissions; }
public String getOwner() { return owner; }
public void setOwner(String owner) { this.owner = owner; }
}
/**
* Product attestation
*/
public class ProductAttestation {
private final Map<Path, ProductInfo> products;
private final Map<Path, String> errors;
public ProductAttestation() {
this.products = new HashMap<>();
this.errors = new HashMap<>();
}
public void addProduct(Path path, ProductInfo info) {
products.put(path, info);
}
public void addError(Path path, String error) {
errors.put(path, error);
}
// Getters
public Map<Path, ProductInfo> getProducts() { return Collections.unmodifiableMap(products); }
public Map<Path, String> getErrors() { return Collections.unmodifiableMap(errors); }
public boolean hasErrors() { return !errors.isEmpty(); }
}
/**
* Product information
*/
public class ProductInfo {
private String path;
private long size;
private long lastModified;
private Map<String, String> hashes;
private String permissions;
private String owner;
private String artifactUri;
public ProductInfo() {
this.hashes = new HashMap<>();
}
// Getters and setters
public String getPath() { return path; }
public void setPath(String path) { this.path = path; }
public long getSize() { return size; }
public void setSize(long size) { this.size = size; }
public long getLastModified() { return lastModified; }
public void setLastModified(long lastModified) { this.lastModified = lastModified; }
public Map<String, String> getHashes() { return Collections.unmodifiableMap(hashes); }
public void addHash(String algorithm, String hash) { hashes.put(algorithm, hash); }
public String getPermissions() { return permissions; }
public void setPermissions(String permissions) { this.permissions = permissions; }
public String getOwner() { return owner; }
public void setOwner(String owner) { this.owner = owner; }
public String getArtifactUri() { return artifactUri; }
public void setArtifactUri(String artifactUri) { this.artifactUri = artifactUri; }
}
/**
* Provenance attestation
*/
public class ProvenanceAttestation {
private String buildId;
private String buildType;
private String builder;
private String invocationId;
private Instant startedAt;
private Instant finishedAt;
private Map<String, Object> buildConfig;
private Map<Path, MaterialInfo> materials;
private Map<Path, ProductInfo> products;
private List<BuildStep> steps;
private Map<String, Object> metadata;
private SLSALevel slsaLevel;
// Getters and setters
public String getBuildId() { return buildId; }
public void setBuildId(String buildId) { this.buildId = buildId; }
public String getBuildType() { return buildType; }
public void setBuildType(String buildType) { this.buildType = buildType; }
public String getBuilder() { return builder; }
public void setBuilder(String builder) { this.builder = builder; }
public String getInvocationId() { return invocationId; }
public void setInvocationId(String invocationId) { this.invocationId = invocationId; }
public Instant getStartedAt() { return startedAt; }
public void setStartedAt(Instant startedAt) { this.startedAt = startedAt; }
public Instant getFinishedAt() { return finishedAt; }
public void setFinishedAt(Instant finishedAt) { this.finishedAt = finishedAt; }
public Map<String, Object> getBuildConfig() { return buildConfig; }
public void setBuildConfig(Map<String, Object> buildConfig) { this.buildConfig = buildConfig; }
public Map<Path, MaterialInfo> getMaterials() { return materials; }
public void setMaterials(Map<Path, MaterialInfo> materials) { this.materials = materials; }
public Map<Path, ProductInfo> getProducts() { return products; }
public void setProducts(Map<Path, ProductInfo> products) { this.products = products; }
public List<BuildStep> getSteps() { return steps; }
public void setSteps(List<BuildStep> steps) { this.steps = steps; }
public Map<String, Object> getMetadata() { return metadata; }
public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; }
public SLSALevel getSlsaLevel() { return slsaLevel; }
public void setSlsaLevel(SLSALevel slsaLevel) { this.slsaLevel = slsaLevel; }
}
/**
* Link metadata (in-toto link format)
*/
public class LinkMetadata {
private String name;
private Map<Path, MaterialInfo> materials;
private Map<Path, ProductInfo> products;
private Map<String, Object> byProducts;
private String command;
private Map<String, String> environment;
private Path workingDir;
// Getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Map<Path, MaterialInfo> getMaterials() { return materials; }
public void setMaterials(Map<Path, MaterialInfo> materials) { this.materials = materials; }
public Map<Path, ProductInfo> getProducts() { return products; }
public void setProducts(Map<Path, ProductInfo> products) { this.products = products; }
public Map<String, Object> getByProducts() { return byProducts; }
public void setByProducts(Map<String, Object> byProducts) { this.byProducts = byProducts; }
public String getCommand() { return command; }
public void setCommand(String command) { this.command = command; }
public Map<String, String> getEnvironment() { return environment; }
public void setEnvironment(Map<String, String> environment) { this.environment = environment; }
public Path getWorkingDir() { return workingDir; }
public void setWorkingDir(Path workingDir) { this.workingDir = workingDir; }
}
/**
* Signed attestation
*/
public class SignedAttestation {
private LinkMetadata linkMetadata;
private Signature signature;
private String keyId;
private Instant signingTime;
// Getters and setters
public LinkMetadata getLinkMetadata() { return linkMetadata; }
public void setLinkMetadata(LinkMetadata linkMetadata) { this.linkMetadata = linkMetadata; }
public Signature getSignature() { return signature; }
public void setSignature(Signature signature) { this.signature = signature; }
public String getKeyId() { return keyId; }
public void setKeyId(String keyId) { this.keyId = keyId; }
public Instant getSigningTime() { return signingTime; }
public void setSigningTime(Instant signingTime) { this.signingTime = signingTime; }
}
/**
* Attestation result
*/
public class AttestationResult {
private final BuildContext context;
private StepAttestation stepAttestation;
private MaterialAttestation materialAttestation;
private ProductAttestation productAttestation;
private ProvenanceAttestation provenanceAttestation;
private LinkMetadata linkMetadata;
private SignedAttestation signedAttestation;
private VerificationResult verificationResult;
private PolicyCompliance policyCompliance;
private boolean success;
private String error;
private long generationTime;
public AttestationResult(BuildContext context) {
this.context = context;
}
// Getters and setters
public BuildContext getContext() { return context; }
public StepAttestation getStepAttestation() { return stepAttestation; }
public void setStepAttestation(StepAttestation stepAttestation) { this.stepAttestation = stepAttestation; }
public MaterialAttestation getMaterialAttestation() { return materialAttestation; }
public void setMaterialAttestation(MaterialAttestation materialAttestation) { this.materialAttestation = materialAttestation; }
public ProductAttestation getProductAttestation() { return productAttestation; }
public void setProductAttestation(ProductAttestation productAttestation) { this.productAttestation = productAttestation; }
public ProvenanceAttestation getProvenanceAttestation() { return provenanceAttestation; }
public void setProvenanceAttestation(ProvenanceAttestation provenanceAttestation) { this.provenanceAttestation = provenanceAttestation; }
public LinkMetadata getLinkMetadata() { return linkMetadata; }
public void setLinkMetadata(LinkMetadata linkMetadata) { this.linkMetadata = linkMetadata; }
public SignedAttestation getSignedAttestation() { return signedAttestation; }
public void setSignedAttestation(SignedAttestation signedAttestation) { this.signedAttestation = signedAttestation; }
public VerificationResult getVerificationResult() { return verificationResult; }
public void setVerificationResult(VerificationResult verificationResult) { this.verificationResult = verificationResult; }
public PolicyCompliance getPolicyCompliance() { return policyCompliance; }
public void setPolicyCompliance(PolicyCompliance policyCompliance) { this.policyCompliance = policyCompliance; }
public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public String getError() { return error; }
public void setError(String error) { this.error = error; }
public long getGenerationTime() { return generationTime; }
public void setGenerationTime(long generationTime) { this.generationTime = generationTime; }
}
/**
* SLSA provenance model
*/
public class SLSAProvenance {
private Builder builder;
private String buildType;
private Invocation invocation;
private Map<String, Object> buildConfig;
private Map<String, Object> metadata;
private List<Material> materials;
private List<Product> products;
// Inner classes
public static class Builder {
private String id;
private Map<String, String> builderDependencies;
private String version;
// Getters and setters
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public Map<String, String> getBuilderDependencies() { return builderDependencies; }
public void setBuilderDependencies(Map<String, String> builderDependencies) { this.builderDependencies = builderDependencies; }
public String getVersion() { return version; }
public void setVersion(String version) { this.version = version; }
}
public static class Invocation {
private Map<String, Object> configSource;
private Map<String, Object> parameters;
private Map<String, Object> environment;
// Getters and setters
public Map<String, Object> getConfigSource() { return configSource; }
public void setConfigSource(Map<String, Object> configSource) { this.configSource = configSource; }
public Map<String, Object> getParameters() { return parameters; }
public void setParameters(Map<String, Object> parameters) { this.parameters = parameters; }
public Map<String, Object> getEnvironment() { return environment; }
public void setEnvironment(Map<String, Object> environment) { this.environment = environment; }
}
public static class Material {
private String uri;
private Map<String, String> digest;
private Map<String, Object> annotations;
// Getters and setters
public String getUri() { return uri; }
public void setUri(String uri) { this.uri = uri; }
public Map<String, String> getDigest() { return digest; }
public void setDigest(Map<String, String> digest) { this.digest = digest; }
public Map<String, Object> getAnnotations() { return annotations; }
public void setAnnotations(Map<String, Object> annotations) { this.annotations = annotations; }
}
public static class Product {
private String uri;
private Map<String, String> digest;
private String name;
// Getters and setters
public String getUri() { return uri; }
public void setUri(String uri) { this.uri = uri; }
public Map<String, String> getDigest() { return digest; }
public void setDigest(Map<String, String> digest) { this.digest = digest; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
// Getters and setters
public Builder getBuilder() { return builder; }
public void setBuilder(Builder builder) { this.builder = builder; }
public String getBuildType() { return buildType; }
public void setBuildType(String buildType) { this.buildType = buildType; }
public Invocation getInvocation() { return invocation; }
public void setInvocation(Invocation invocation) { this.invocation = invocation; }
public Map<String, Object> getBuildConfig() { return buildConfig; }
public void setBuildConfig(Map<String, Object> buildConfig) { this.buildConfig = buildConfig; }
public Map<String, Object> getMetadata() { return metadata; }
public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; }
public List<Material> getMaterials() { return materials; }
public void setMaterials(List<Material> materials) { this.materials = materials; }
public List<Product> getProducts() { return products; }
public void setProducts(List<Product> products) { this.products = products; }
}
/**
* SLSA levels
*/
public enum SLSALevel {
LEVEL_0,
LEVEL_1,
LEVEL_2,
LEVEL_3,
LEVEL_4
}

Key Management and Signing

package com.titliel.intoto;
import java.security.*;
import java.security.spec.*;
import java.util.*;
/**
* Key management for attestation signing and verification
*/
public class KeyManager {
private PrivateKey privateKey;
private PublicKey publicKey;
private String keyId;
private String keyAlgorithm;
public void initialize() {
try {
// Load or generate keys
loadKeys();
// Generate key ID
keyId = generateKeyId();
SecurityLogger.info("Key manager initialized with key ID: {}", keyId);
} catch (Exception e) {
throw new InTotoException("Failed to initialize key manager", e);
}
}
private void loadKeys() throws Exception {
// Try to load existing keys
if (!tryLoadExistingKeys()) {
// Generate new keys
generateKeys();
saveKeys();
}
}
private boolean tryLoadExistingKeys() {
try {
Path privateKeyPath = getPrivateKeyPath();
Path publicKeyPath = getPublicKeyPath();
if (Files.exists(privateKeyPath) && Files.exists(publicKeyPath)) {
// Load existing keys
loadKeysFromFiles(privateKeyPath, publicKeyPath);
return true;
}
} catch (Exception e) {
SecurityLogger.warn("Failed to load existing keys", e);
}
return false;
}
private void generateKeys() throws Exception {
// Generate RSA key pair
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(4096);
KeyPair keyPair = keyGen.generateKeyPair();
privateKey = keyPair.getPrivate();
publicKey = keyPair.getPublic();
keyAlgorithm = "rsa";
SecurityLogger.info("Generated new RSA 4096-bit key pair");
}
private void saveKeys() throws Exception {
// Save private key
Path privateKeyPath = getPrivateKeyPath();
Files.createDirectories(privateKeyPath.getParent());
byte[] privateKeyBytes = privateKey.getEncoded();
Files.write(privateKeyPath, privateKeyBytes);
// Save public key
Path publicKeyPath = getPublicKeyPath();
byte[] publicKeyBytes = publicKey.getEncoded();
Files.write(publicKeyPath, publicKeyBytes);
// Set secure permissions on private key
setSecurePermissions(privateKeyPath);
SecurityLogger.info("Keys saved to: {}", privateKeyPath.getParent());
}
private void loadKeysFromFiles(Path privateKeyPath, Path publicKeyPath) throws Exception {
// Load private key
byte[] privateKeyBytes = Files.readAllBytes(privateKeyPath);
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
privateKey = keyFactory.generatePrivate(privateKeySpec);
// Load public key
byte[] publicKeyBytes = Files.readAllBytes(publicKeyPath);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
publicKey = keyFactory.generatePublic(publicKeySpec);
keyAlgorithm = "rsa";
SecurityLogger.info("Loaded existing keys from: {}", privateKeyPath.getParent());
}
private String generateKeyId() {
try {
// Generate key ID from public key fingerprint
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] fingerprint = digest.digest(publicKey.getEncoded());
// Take first 16 bytes for key ID
StringBuilder keyIdBuilder = new StringBuilder();
for (int i = 0; i < 16; i++) {
keyIdBuilder.append(String.format("%02x", fingerprint[i]));
}
return keyIdBuilder.toString();
} catch (Exception e) {
throw new InTotoException("Failed to generate key ID", e);
}
}
/**
* Sign data with private key
*/
public Signature sign(byte[] data) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data);
byte[] signatureBytes = signature.sign();
SignatureResult result = new SignatureResult();
result.setAlgorithm("SHA256withRSA");
result.setSignature(signatureBytes);
result.setKeyId(keyId);
result.setTimestamp(Instant.now());
return result;
}
/**
* Verify signature
*/
public boolean verify(LinkMetadata link, Signature signature) throws Exception {
// Serialize link metadata
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(link);
byte[] data = json.getBytes();
return verify(data, signature);
}
/**
* Verify signature for raw data
*/
public boolean verify(byte[] data, Signature signature) throws Exception {
Signature verifier = Signature.getInstance(signature.getAlgorithm());
verifier.initVerify(publicKey);
verifier.update(data);
return verifier.verify(signature.getSignature());
}
/**
* Get public key in PEM format
*/
public String getPublicKeyPem() {
try {
String base64Key = Base64.getEncoder().encodeToString(publicKey.getEncoded());
return String.format("-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----",
base64Key.replaceAll("(.{64})", "$1\n").trim());
} catch (Exception e) {
throw new InTotoException("Failed to generate PEM format", e);
}
}
/**
* Get key ID
*/
public String getKeyId() {
return keyId;
}
private Path getPrivateKeyPath() {
return Paths.get(InTotoConfig.getInstance().getKeyDirectory(), "private.key");
}
private Path getPublicKeyPath() {
return Paths.get(InTotoConfig.getInstance().getKeyDirectory(), "public.key");
}
private void setSecurePermissions(Path path) throws IOException {
// Set restrictive permissions on private key
if (System.getProperty("os.name").toLowerCase().contains("linux")) {
Files.setPosixFilePermissions(path, Set.of(
PosixFilePermission.OWNER_READ,
PosixFilePermission.OWNER_WRITE
));
}
}
}
/**
* Signature representation
*/
public class Signature {
private String algorithm;
private byte[] signature;
private String keyId;
private Instant timestamp;
// Getters and setters
public String getAlgorithm() { return algorithm; }
public void setAlgorithm(String algorithm) { this.algorithm = algorithm; }
public byte[] getSignature() { return signature; }
public void setSignature(byte[] signature) { this.signature = signature; }
public String getKeyId() { return keyId; }
public void setKeyId(String keyId) { this.keyId = keyId; }
public Instant getTimestamp() { return timestamp; }
public void setTimestamp(Instant timestamp) { this.timestamp = timestamp; }
}

Verification and Policy Engine

package com.titliel.intoto;
import java.util.*;
/**
* Attestation verification engine
*/
public class AttestationVerifier {
private final KeyManager keyManager;
private final PolicyEngine policyEngine;
public AttestationVerifier() {
this.keyManager = new KeyManager();
this.policyEngine = new PolicyEngine();
}
/**
* Verify signed attestation
*/
public VerificationResult verify(SignedAttestation attestation) {
VerificationResult result = new VerificationResult();
try {
// Verify signature
boolean signatureValid = keyManager.verify(
attestation.getLinkMetadata(),
attestation.getSignature()
);
result.setSignatureValid(signatureValid);
// Verify link metadata integrity
result.setMetadataValid(verifyMetadata(attestation.getLinkMetadata()));
// Verify material-product relationships
result.setRelationshipsValid(
verifyMaterialProductRelationships(attestation.getLinkMetadata()));
// Calculate overall score
result.calculateScore();
} catch (Exception e) {
result.setError(e.getMessage());
SecurityLogger.error("Attestation verification failed", e);
}
return result;
}
/**
* Verify metadata integrity
*/
private boolean verifyMetadata(LinkMetadata link) {
// Check required fields
if (link.getName() == null || link.getName().isEmpty()) {
return false;
}
if (link.getMaterials() == null || link.getMaterials().isEmpty()) {
return false;
}
if (link.getProducts() == null || link.getProducts().isEmpty()) {
return false;
}
// Verify material hashes
for (MaterialInfo material : link.getMaterials().values()) {
if (!verifyMaterialHashes(material)) {
return false;
}
}
// Verify product hashes
for (ProductInfo product : link.getProducts().values()) {
if (!verifyProductHashes(product)) {
return false;
}
}
return true;
}
/**
* Verify material hashes
*/
private boolean verifyMaterialHashes(MaterialInfo material) {
if (material.getHashes() == null || material.getHashes().isEmpty()) {
return false;
}
// At least one strong hash algorithm should be present
Set<String> strongAlgorithms = Set.of("sha256", "sha512");
return material.getHashes().keySet().stream()
.anyMatch(strongAlgorithms::contains);
}
/**
* Verify product hashes
*/
private boolean verifyProductHashes(ProductInfo product) {
if (product.getHashes() == null || product.getHashes().isEmpty()) {
return false;
}
// At least one strong hash algorithm should be present
Set<String> strongAlgorithms = Set.of("sha256", "sha512");
return product.getHashes().keySet().stream()
.anyMatch(strongAlgorithms::contains);
}
/**
* Verify material-product relationships
*/
private boolean verifyMaterialProductRelationships(LinkMetadata link) {
// Basic validation: ensure materials and products are different
Set<Path> materialPaths = link.getMaterials().keySet();
Set<Path> productPaths = link.getProducts().keySet();
// Check for obvious inconsistencies
if (materialPaths.isEmpty() || productPaths.isEmpty()) {
return false;
}
// Materials and products should generally be different files
// (though self-modification is possible)
return true;
}
/**
* Verify supply chain continuity
*/
public ChainVerificationResult verifyChain(List<SignedAttestation> chain) {
ChainVerificationResult result = new ChainVerificationResult();
if (chain.isEmpty()) {
result.setError("Empty attestation chain");
return result;
}
// Verify each attestation individually
List<VerificationResult> individualResults = new ArrayList<>();
for (SignedAttestation attestation : chain) {
VerificationResult individual = verify(attestation);
individualResults.add(individual);
result.addIndividualResult(attestation, individual);
}
// Verify chain continuity
boolean chainValid = verifyChainContinuity(chain);
result.setChainContinuityValid(chainValid);
// Verify policy compliance across chain
PolicyCompliance chainCompliance = verifyChainPolicyCompliance(chain);
result.setPolicyCompliance(chainCompliance);
// Calculate overall chain integrity
result.calculateChainIntegrity();
return result;
}
/**
* Verify chain continuity
*/
private boolean verifyChainContinuity(List<SignedAttestation> chain) {
for (int i = 0; i < chain.size() - 1; i++) {
SignedAttestation current = chain.get(i);
SignedAttestation next = chain.get(i + 1);
if (!verifyStepContinuity(current, next)) {
return false;
}
}
return true;
}
/**
* Verify continuity between two steps
*/
private boolean verifyStepContinuity(SignedAttestation current, SignedAttestation next) {
// Get products from current step
Map<Path, ProductInfo> currentProducts = current.getLinkMetadata().getProducts();
// Get materials from next step
Map<Path, MaterialInfo> nextMaterials = next.getLinkMetadata().getMaterials();
// Verify that next step's materials include current step's products
// This is a simplified check - real implementation would be more complex
for (Path productPath : currentProducts.keySet()) {
MaterialInfo nextMaterial = nextMaterials.get(productPath);
if (nextMaterial == null) {
// Product not found in next step's materials
// Could be acceptable if product is not consumed
continue;
}
// Verify hash consistency
ProductInfo currentProduct = currentProducts.get(productPath);
if (!verifyHashConsistency(currentProduct, nextMaterial)) {
return false;
}
}
return true;
}
/**
* Verify hash consistency between product and material
*/
private boolean verifyHashConsistency(ProductInfo product, MaterialInfo material) {
// Check if at least one hash algorithm matches
for (Map.Entry<String, String> productHash : product.getHashes().entrySet()) {
String materialHash = material.getHashes().get(productHash.getKey());
if (materialHash != null && materialHash.equals(productHash.getValue())) {
return true;
}
}
return false;
}
/**
* Verify policy compliance across chain
*/
private PolicyCompliance verifyChainPolicyCompliance(List<SignedAttestation> chain) {
PolicyCompliance compliance = new PolicyCompliance();
// Check each attestation against chain policies
for (SignedAttestation attestation : chain) {
PolicyCompliance individual = policyEngine.evaluateCompliance(attestation);
compliance.merge(individual);
}
// Check chain-level policies
compliance.merge(policyEngine.evaluateChainCompliance(chain));
return compliance;
}
}
/**
* Verification result
*/
public class VerificationResult {
private boolean signatureValid;
private boolean metadataValid;
private boolean relationshipsValid;
private double score;
private String error;
public void calculateScore() {
int validCount = 0;
int totalCount = 0;
if (signatureValid) validCount++;
totalCount++;
if (metadataValid) validCount++;
totalCount++;
if (relationshipsValid) validCount++;
totalCount++;
this.score = (double) validCount / totalCount * 100.0;
}
// Getters and setters
public boolean isSignatureValid() { return signatureValid; }
public void setSignatureValid(boolean signatureValid) { this.signatureValid = signatureValid; }
public boolean isMetadataValid() { return metadataValid; }
public void setMetadataValid(boolean metadataValid) { this.metadataValid = metadataValid; }
public boolean isRelationshipsValid() { return relationshipsValid; }
public void setRelationshipsValid(boolean relationshipsValid) { this.relationshipsValid = relationshipsValid; }
public double getScore() { return score; }
public void setScore(double score) { this.score = score; }
public String getError() { return error; }
public void setError(String error) { this.error = error; }
public boolean isSuccess() {
return signatureValid && metadataValid && relationshipsValid && score >= 80.0;
}
}
/**
* Chain verification result
*/
public class ChainVerificationResult {
private final Map<SignedAttestation, VerificationResult> individualResults;
private boolean chainContinuityValid;
private PolicyCompliance policyCompliance;
private double chainIntegrityScore;
private String error;
public ChainVerificationResult() {
this.individualResults = new HashMap<>();
}
public void addIndividualResult(SignedAttestation attestation, VerificationResult result) {
individualResults.put(attestation, result);
}
public void calculateChainIntegrity() {
if (individualResults.isEmpty()) {
chainIntegrityScore = 0.0;
return;
}
// Calculate average of individual scores
double totalScore = individualResults.values().stream()
.mapToDouble(VerificationResult::getScore)
.sum();
double averageScore = totalScore / individualResults.size();
// Adjust for chain continuity
if (chainContinuityValid) {
averageScore *= 1.1; // Bonus for continuity
} else {
averageScore *= 0.5; // Penalty for broken chain
}
// Adjust for policy compliance
if (policyCompliance != null && policyCompliance.isCompliant()) {
averageScore *= 1.05; // Bonus for policy compliance
}
chainIntegrityScore = Math.min(averageScore, 100.0);
}
// Getters and setters
public Map<SignedAttestation, VerificationResult> getIndividualResults() { 
return Collections.unmodifiableMap(individualResults); 
}
public boolean isChainContinuityValid() { return chainContinuityValid; }
public void setChainContinuityValid(boolean chainContinuityValid) { 
this.chainContinuityValid = chainContinuityValid; 
}
public PolicyCompliance getPolicyCompliance() { return policyCompliance; }
public void setPolicyCompliance(PolicyCompliance policyCompliance) { 
this.policyCompliance = policyCompliance; 
}
public double getChainIntegrityScore() { return chainIntegrityScore; }
public void setChainIntegrityScore(double chainIntegrityScore) { 
this.chainIntegrityScore = chainIntegrityScore; 
}
public String getError() { return error; }
public void setError(String error) { this.error = error; }
public boolean isChainValid() {
return chainIntegrityScore >= 80.0 && 
chainContinuityValid && 
(policyCompliance == null || policyCompliance.isCompliant());
}
}
/**
* Policy engine for compliance checking
*/
public class PolicyEngine {
private final List<PolicyRule> rules;
private final Map<String, SupplyChainPolicy> policies;
public PolicyEngine() {
this.rules = new ArrayList<>();
this.policies = new HashMap<>();
loadDefaultRules();
}
private void loadDefaultRules() {
// Add default policy rules
rules.add(new SignaturePolicyRule());
rules.add(new HashPolicyRule());
rules.add(new StepNamePolicyRule());
rules.add(new MaterialSourcePolicyRule());
rules.add(new ProductIntegrityPolicyRule());
}
public void loadPolicies() {
// Load policies from configuration
InTotoConfig config = InTotoConfig.getInstance();
Path policyDir = Paths.get(config.getPolicyDirectory());
try {
if (Files.exists(policyDir)) {
Files.list(policyDir)
.filter(path -> path.toString().endsWith(".json"))
.forEach(this::loadPolicyFile);
}
} catch (IOException e) {
SecurityLogger.warn("Failed to load policies from directory: {}", policyDir, e);
}
}
private void loadPolicyFile(Path policyFile) {
try {
ObjectMapper mapper = new ObjectMapper();
SupplyChainPolicy policy = mapper.readValue(policyFile.toFile(), SupplyChainPolicy.class);
policies.put(policy.getName(), policy);
SecurityLogger.info("Loaded policy: {}", policy.getName());
} catch (IOException e) {
SecurityLogger.warn("Failed to load policy file: {}", policyFile, e);
}
}
/**
* Evaluate attestation compliance
*/
public PolicyCompliance evaluateCompliance(SignedAttestation attestation) {
PolicyCompliance compliance = new PolicyCompliance();
for (PolicyRule rule : rules) {
RuleResult result = rule.evaluate(attestation);
compliance.addRuleResult(rule.getName(), result);
}
// Check against specific policies
for (SupplyChainPolicy policy : policies.values()) {
if (policy.appliesTo(attestation)) {
PolicyEvaluation evaluation = policy.evaluate(attestation);
compliance.addPolicyEvaluation(policy.getName(), evaluation);
}
}
compliance.calculateCompliance();
return compliance;
}
/**
* Evaluate chain compliance
*/
public PolicyCompliance evaluateChainCompliance(List<SignedAttestation> chain) {
PolicyCompliance compliance = new PolicyCompliance();
// Check chain-level policies
for (SupplyChainPolicy policy : policies.values()) {
if (policy.isChainPolicy()) {
PolicyEvaluation evaluation = policy.evaluateChain(chain);
compliance.addPolicyEvaluation(policy.getName(), evaluation);
}
}
compliance.calculateCompliance();
return compliance;
}
}
/**
* Policy rule interface
*/
interface PolicyRule {
String getName();
RuleResult evaluate(SignedAttestation attestation);
}
/**
* Signature policy rule
*/
class SignaturePolicyRule implements PolicyRule {
@Override
public String getName() {
return "signature-valid";
}
@Override
public RuleResult evaluate(SignedAttestation attestation) {
RuleResult result = new RuleResult(getName());
try {
// Check signature exists
if (attestation.getSignature() == null) {
result.setPassed(false);
result.setMessage("No signature found");
return result;
}
// Check key ID exists
if (attestation.getKeyId() == null || attestation.getKeyId().isEmpty()) {
result.setPassed(false);
result.setMessage("No key ID found");
return result;
}
// Check signature algorithm
String algorithm = attestation.getSignature().getAlgorithm();
if (!isStrongAlgorithm(algorithm)) {
result.setPassed(false);
result.setMessage("Weak signature algorithm: " + algorithm);
return result;
}
result.setPassed(true);
result.setMessage("Signature valid");
} catch (Exception e) {
result.setPassed(false);
result.setMessage("Signature verification failed: " + e.getMessage());
}
return result;
}
private boolean isStrongAlgorithm(String algorithm) {
return algorithm.contains("SHA256") || algorithm.contains("SHA512");
}
}
/**
* Hash policy rule
*/
class HashPolicyRule implements PolicyRule {
@Override
public String getName() {
return "hash-integrity";
}
@Override
public RuleResult evaluate(SignedAttestation attestation) {
RuleResult result = new RuleResult(getName());
LinkMetadata link = attestation.getLinkMetadata();
// Check materials have strong hashes
for (MaterialInfo material : link.getMaterials().values()) {
if (!hasStrongHash(material.getHashes())) {
result.setPassed(false);
result.setMessage("Material missing strong hash: " + material.getPath());
return result;
}
}
// Check products have strong hashes
for (ProductInfo product : link.getProducts().values()) {
if (!hasStrongHash(product.getHashes())) {
result.setPassed(false);
result.setMessage("Product missing strong hash: " + product.getPath());
return result;
}
}
result.setPassed(true);
result.setMessage("All materials and products have strong hashes");
return result;
}
private boolean hasStrongHash(Map<String, String> hashes) {
if (hashes == null || hashes.isEmpty()) {
return false;
}
return hashes.containsKey("sha256") || hashes.containsKey("sha512");
}
}

Configuration and Usage Examples

```java
package com.titliel.intoto;

import java.nio.file.Paths;
import java.util.*;

/**

  • Configuration management
    */
    public class InTotoConfig { private static InTotoConfig instance;
    private final Properties properties; private InTotoConfig() {
    this.properties = loadProperties();
    } public static synchronized InTotoConfig getInstance() {
    if (instance == null) {
    instance = new InTotoConfig();
    }
    return instance;
    } private Properties loadProperties() {
    Properties props = new Properties(); // Load from system properties props.putAll(System.getProperties()); // Load from configuration file try { Path configFile = Paths.get("intoto.properties"); if (Files.exists(configFile)) { try (InputStream input = Files.newInputStream(configFile)) { props.load(input); } } } catch (IOException e) { // Use defaults } // Load from environment loadFromEnvironment(props); // Set defaults setDefaults(props); return props; } private void loadFrom

Advanced Java Container Security, Sandboxing & Trusted Runtime Environments

https://macronepal.com/blog/sandboxing-java-applications-implementing-landlock-lsm-for-enhanced-container-security/
Explains using Linux Landlock LSM to sandbox Java applications by restricting file system and resource access without root privileges, improving application-level isolation and reducing attack surface.

https://macronepal.com/blog/gvisor-sandbox-integration-in-java-complete-guide/
Explains integrating gVisor with Java to provide a user-space kernel sandbox that intercepts system calls and isolates applications from the host operating system for stronger security.

https://macronepal.com/blog/selinux-for-java-mandatory-access-control-for-jvm-applications/
Explains how SELinux enforces Mandatory Access Control (MAC) policies on Java applications, strictly limiting what files, processes, and network resources the JVM can access.

https://macronepal.com/java/a-comprehensive-guide-to-intel-sgx-sdk-integration-in-java/
Explains Intel SGX integration in Java, allowing sensitive code and data to run inside secure hardware enclaves that remain protected even if the OS is compromised.

https://macronepal.com/blog/building-a-microvm-runtime-with-aws-firecracker-in-java-a-comprehensive-guide/
Explains using AWS Firecracker microVMs with Java to run workloads in lightweight virtual machines that provide strong isolation with near-container performance efficiency.

https://macronepal.com/blog/enforcing-mandatory-access-control-implementing-apparmor-for-java-applications/
Explains AppArmor security profiles for Java applications, enforcing rules that restrict file access, execution rights, and system-level permissions.

https://macronepal.com/blog/rootless-containers-in-java-secure-container-operations-without-root/
Explains running Java applications in rootless containers using Linux user namespaces so containers operate securely without requiring root privileges.

https://macronepal.com/blog/unlocking-container-security-harnessing-user-namespaces-in-java/
Explains Linux user namespaces, which isolate user and group IDs inside containers to improve privilege separation and enhance container security for Java workloads.

https://macronepal.com/blog/secure-bootstrapping-in-java-comprehensive-trust-establishment-framework/
Explains secure bootstrapping in Java, focusing on how systems establish trust during startup using secure key management, identity verification, and trusted configuration loading.

https://macronepal.com/blog/securing-java-applications-with-chainguard-wolfi-a-comprehensive-guide-2/
Explains using Chainguard/Wolfi minimal container images to secure Java applications by reducing unnecessary packages, minimizing vulnerabilities, and providing a hardened runtime environment.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper