Skip to content

Commit

Permalink
adjust x509sanDns and add tests (#188)
Browse files Browse the repository at this point in the history
Signed-off-by: Kevin <kevin.dinh@lissi.id>
  • Loading branch information
Dindexx authored Sep 18, 2024
1 parent 81a3cc8 commit e8633c1
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static FormUrlEncodedContent ToFormUrl(this EncryptedAuthorizationRespons
{
var content = new Dictionary<string, string>
{
{ "response", response.ToString() },
{ "response", response.ToString() }
};

return new FormUrlEncodedContent(content);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,52 +19,36 @@ public static bool IsTrustChainValid(this List<X509Certificate> trustChain)
{
var leafCert = trustChain.First();

var rootCerts =
new HashSet(
trustChain
.Skip(1)
.Where(cert => cert.IssuerDN.Equivalent(cert.SubjectDN))
.Select(cert => new TrustAnchor(cert, null))
.ToList()
);

var intermediateCerts =
new HashSet(
trustChain
.Skip(1)
.Where(cert => !cert.IssuerDN.Equivalent(cert.SubjectDN))
.Append(leafCert)
);

var builderParams =
new PkixBuilderParameters(
rootCerts,
new X509CertStoreSelector
{
Certificate = leafCert
}
)
{
//TODO: Check if CRLs (Certificate Revocation Lists) are valid
IsRevocationEnabled = false
};

builderParams.AddStore(
X509StoreFactory.Create(
"Certificate/Collection",
new X509CollectionStoreParameters(intermediateCerts)
)
);
var rootCerts = new HashSet(
trustChain
.Where(cert => cert.IsSelfSigned())
.Select(cert => new TrustAnchor(cert, null)));

var intermediateCerts = new HashSet(
trustChain
.Where(cert => !cert.IsSelfSigned())
.Append(leafCert));

var storeSelector = new X509CertStoreSelector { Certificate = leafCert };

var builderParams = new PkixBuilderParameters(rootCerts, storeSelector)
{
//TODO: Check if CRLs (Certificate Revocation Lists) are valid
IsRevocationEnabled = false
};

var store = X509StoreFactory.Create(
"Certificate/Collection",
new X509CollectionStoreParameters(intermediateCerts));
builderParams.AddStore(store);

// This throws if validation fails
new PkixCertPathValidator()
.Validate(
new PkixCertPathBuilder()
.Build(builderParams)
.CertPath,
builderParams
);
var path = new PkixCertPathBuilder().Build(builderParams).CertPath;
new PkixCertPathValidator().Validate(path, builderParams);

return true;
}

internal static bool IsSelfSigned(this X509Certificate certificate) =>
certificate.IssuerDN.Equivalent(certificate.SubjectDN);
}
59 changes: 37 additions & 22 deletions src/WalletFramework.Oid4Vc/Oid4Vp/Models/RequestObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,14 @@ public static class RequestObjectExtensions
/// <returns>The validated request object.</returns>
/// <exception cref="InvalidOperationException">Throws when validation fails</exception>
public static RequestObject ValidateJwt(this RequestObject requestObject)
=> ((JwtSecurityToken)requestObject).IsSignatureValid(requestObject.GetLeafCertificate().GetPublicKey())
{
var jwt = (JwtSecurityToken)requestObject;
var pubKey = requestObject.GetLeafCertificate().GetPublicKey();

return jwt.IsSignatureValid(pubKey)
? requestObject
: throw new InvalidOperationException("Invalid JWT Signature");
}

/// <summary>
/// Validates the SAN name of the leaf certificate
Expand All @@ -85,9 +90,8 @@ public static RequestObject ValidateJwt(this RequestObject requestObject)
/// <exception cref="InvalidOperationException">Throws when validation fails</exception>
public static RequestObject ValidateSanName(this RequestObject requestObject)
{
var x509Certificate = new X509Certificate2(
requestObject.GetLeafCertificate().GetEncoded()
);
var encoded = requestObject.GetLeafCertificate().GetEncoded();
var x509Certificate = new X509Certificate2(encoded);

return GetSanDnsNames(x509Certificate).Any(sanDnsName => requestObject.ClientId.EndsWith(sanDnsName.Split("*").Last()))
? requestObject
Expand Down Expand Up @@ -121,25 +125,36 @@ private static IEnumerable<string> GetSanDnsNames(X509Certificate2 certificate)
/// </summary>
/// <returns>The validated request object</returns>
/// <exception cref="InvalidOperationException">Throws when validation fails</exception>
public static RequestObject ValidateTrustChain(this RequestObject requestObject) =>
requestObject
.GetCertificates()
.IsTrustChainValid()
? requestObject
: throw new InvalidOperationException("Validation of trust chain failed");

internal static List<X509Certificate> GetCertificates(this RequestObject requestObject) =>
Parse(((JwtSecurityToken)requestObject).Header.X5c)
.Select(
certAsJToken =>
new X509CertificateParser()
.ReadCertificate(
FromBase64String(certAsJToken.ToString())
)
)
.ToList();
public static RequestObject ValidateTrustChain(this RequestObject requestObject)
{
var certificates = requestObject.GetCertificates();
if (certificates.Count == 1)
{
if (certificates.First().IsSelfSigned())
return requestObject;
else
throw new InvalidOperationException("TrustChain must not consist of only one non-self-signed certificate");
}
else
{
if (certificates.IsTrustChainValid())
return requestObject;
else
throw new InvalidOperationException("Validation of trust chain failed");
}
}

internal static List<X509Certificate> GetCertificates(this RequestObject requestObject)
{
var x5C = ((JwtSecurityToken)requestObject).Header.X5c;
return Parse(x5C).Select(
certAsJToken =>
{
var certBytes = FromBase64String(certAsJToken.ToString());
return new X509CertificateParser().ReadCertificate(certBytes);
}).ToList();
}

internal static X509Certificate GetLeafCertificate(this RequestObject requestObject) =>
GetCertificates(requestObject).First();
}

Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ public Oid4VpClientService(
.PresentationDefinition
.InputDescriptors;

// TODO: This is only a hack until the encryption response is implemented
var mdocNonce = Option<Nonce>.None;

var presentationMapTasks = credentials.Select(async credential =>
Expand Down Expand Up @@ -291,16 +290,18 @@ await _oid4VpRecordService.StoreAsync(
}

//TODO: Refactor this C'' method into current flows (too much duplicate code)
public async Task<Uri?> SendAuthorizationResponseAsync(AuthorizationRequest authorizationRequest, IEnumerable<SelectedCredential> selectedCredentials,
IssuanceSession issuanceSession, CombinedWalletAttestation? clientAttestation = null)
public async Task<Uri?> SendAuthorizationResponseAsync(
AuthorizationRequest authorizationRequest,
IEnumerable<SelectedCredential> selectedCredentials,
IssuanceSession issuanceSession,
CombinedWalletAttestation? clientAttestation = null)
{
var credentials = selectedCredentials.ToList();

var inputDescriptors = authorizationRequest
.PresentationDefinition
.InputDescriptors;

// TODO: This is only a hack until the encryption response is implemented
var mdocNonce = Option<Nonce>.None;

var presentationMapTasks = credentials.Select(async credential =>
Expand Down
Loading

0 comments on commit e8633c1

Please sign in to comment.