commit
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				Build Test Deploy / build-test (push) Has been cancelled
				
			
		
			
				
	
				Build Test Deploy / authority-container (push) Has been cancelled
				
			
		
			
				
	
				Build Test Deploy / docs (push) Has been cancelled
				
			
		
			
				
	
				Build Test Deploy / deploy (push) Has been cancelled
				
			
		
			
				
	
				Docs CI / lint-and-preview (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	Build Test Deploy / build-test (push) Has been cancelled
				
			Build Test Deploy / authority-container (push) Has been cancelled
				
			Build Test Deploy / docs (push) Has been cancelled
				
			Build Test Deploy / deploy (push) Has been cancelled
				
			Docs CI / lint-and-preview (push) Has been cancelled
				
			This commit is contained in:
		
							
								
								
									
										83
									
								
								src/StellaOps.Vexer.Attestation/Dsse/VexDsseBuilder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/StellaOps.Vexer.Attestation/Dsse/VexDsseBuilder.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Security.Cryptography; | ||||
| using System.Text; | ||||
| using System.Text.Json; | ||||
| using System.Text.Json.Serialization; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using StellaOps.Vexer.Attestation.Models; | ||||
| using StellaOps.Vexer.Attestation.Signing; | ||||
| using StellaOps.Vexer.Core; | ||||
|  | ||||
| namespace StellaOps.Vexer.Attestation.Dsse; | ||||
|  | ||||
| public sealed class VexDsseBuilder | ||||
| { | ||||
|     private const string PayloadType = "application/vnd.in-toto+json"; | ||||
|  | ||||
|     private readonly IVexSigner _signer; | ||||
|     private readonly ILogger<VexDsseBuilder> _logger; | ||||
|     private readonly JsonSerializerOptions _serializerOptions; | ||||
|  | ||||
|     public VexDsseBuilder(IVexSigner signer, ILogger<VexDsseBuilder> logger) | ||||
|     { | ||||
|         _signer = signer ?? throw new ArgumentNullException(nameof(signer)); | ||||
|         _logger = logger ?? throw new ArgumentNullException(nameof(logger)); | ||||
|         _serializerOptions = new JsonSerializerOptions | ||||
|         { | ||||
|             PropertyNamingPolicy = JsonNamingPolicy.CamelCase, | ||||
|             DefaultIgnoreCondition = JsonIgnoreCondition.Never, | ||||
|             WriteIndented = false, | ||||
|         }; | ||||
|         _serializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); | ||||
|     } | ||||
|  | ||||
|     public async ValueTask<DsseEnvelope> CreateEnvelopeAsync( | ||||
|         VexAttestationRequest request, | ||||
|         IReadOnlyDictionary<string, string>? metadata, | ||||
|         CancellationToken cancellationToken) | ||||
|     { | ||||
|         ArgumentNullException.ThrowIfNull(request); | ||||
|  | ||||
|         var predicate = VexAttestationPredicate.FromRequest(request, metadata); | ||||
|         var subject = new VexInTotoSubject( | ||||
|             request.ExportId, | ||||
|             new Dictionary<string, string>(StringComparer.Ordinal) | ||||
|             { | ||||
|                 { request.Artifact.Algorithm.ToLowerInvariant(), request.Artifact.Digest } | ||||
|             }); | ||||
|  | ||||
|         var statement = new VexInTotoStatement( | ||||
|             VexInTotoStatement.InTotoType, | ||||
|             "https://stella-ops.org/attestations/vex-export", | ||||
|             new[] { subject }, | ||||
|             predicate); | ||||
|  | ||||
|         var payloadBytes = JsonSerializer.SerializeToUtf8Bytes(statement, _serializerOptions); | ||||
|         var signatureResult = await _signer.SignAsync(payloadBytes, cancellationToken).ConfigureAwait(false); | ||||
|  | ||||
|         var envelope = new DsseEnvelope( | ||||
|             Convert.ToBase64String(payloadBytes), | ||||
|             PayloadType, | ||||
|             new[] { new DsseSignature(signatureResult.Signature, signatureResult.KeyId) }); | ||||
|  | ||||
|         _logger.LogDebug("DSSE envelope created for export {ExportId}", request.ExportId); | ||||
|         return envelope; | ||||
|     } | ||||
|  | ||||
|     public static string ComputeEnvelopeDigest(DsseEnvelope envelope) | ||||
|     { | ||||
|         ArgumentNullException.ThrowIfNull(envelope); | ||||
|         var envelopeJson = JsonSerializer.Serialize(envelope, new JsonSerializerOptions | ||||
|         { | ||||
|             PropertyNamingPolicy = JsonNamingPolicy.CamelCase, | ||||
|             DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, | ||||
|         }); | ||||
|         var bytes = Encoding.UTF8.GetBytes(envelopeJson); | ||||
|         var hash = SHA256.HashData(bytes); | ||||
|         return "sha256:" + Convert.ToHexString(hash).ToLowerInvariant(); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user