public void ParsePaPkAsReq_SignedAuthPack_ParseAuthPack() { KrbPaPkAsReq asreq = KrbPaPkAsReq.Decode(signedPkAsReq); SignedCms signedCms = new SignedCms(); signedCms.Decode(asreq.SignedAuthPack.ToArray()); signedCms.CheckSignature(verifySignatureOnly: true); KrbAuthPack authPack = KrbAuthPack.Decode(signedCms.ContentInfo.Content); Assert.IsNotNull(authPack); var param = authPack.ClientPublicValue.Algorithm.Parameters.Value; var b64 = Convert.ToBase64String(param.ToArray()); var domainParams = KrbDiffieHellmanDomainParameters.DecodeSpecial(param); Assert.IsNotNull(domainParams); var special = domainParams.EncodeSpecial(); Assert.IsTrue(special.Span.SequenceEqual(param.ToArray())); var decodedPk = CryptEncode.CryptDecodePublicParameter(authPack.ClientPublicValue.SubjectPublicKey).Slice(16); }
public override void PreValidate(PreAuthenticationContext preauth) { if (preauth == null) { throw new ArgumentNullException(nameof(preauth)); } var asReq = (KrbKdcReq)preauth.Message; var paPk = asReq.PaData.FirstOrDefault(p => p.Type == PaDataType.PA_PK_AS_REQ); if (paPk == null) { return; } var pkreq = KrbPaPkAsReq.Decode(paPk.Value); var signedCms = new SignedCms(); signedCms.Decode(pkreq.SignedAuthPack.ToArray()); var state = new PkInitState { PkInitRequest = pkreq, Cms = signedCms }; state.ClientCertificate.AddRange(signedCms.Certificates); preauth.PreAuthenticationState[PaDataType.PA_PK_AS_REQ] = state; }
/// <summary> /// Applies credential-specific changes to the KDC-REQ message and is what supplies the PKINIT properties to the request. /// </summary> /// <param name="req">The <see cref="KrbKdcReq"/> that will be modified.</param> public override void TransformKdcReq(KrbKdcReq req) { agreement = StartKeyAgreement(); // We don't support the straight RSA mode because // it doesn't rely on ephemeral key agreement // which isn't great security-wise if (agreement == null) { throw OnlyKeyAgreementSupportedException(); } var padata = req.PaData.ToList(); KrbAuthPack authPack; if (SupportsEllipticCurveDiffieHellman) { authPack = CreateEllipticCurveDiffieHellmanAuthPack(req.Body); } else if (SupportsDiffieHellman) { authPack = CreateDiffieHellmanAuthPack(req.Body); } else { throw OnlyKeyAgreementSupportedException(); } KerberosConstants.Now(out authPack.PKAuthenticator.CTime, out authPack.PKAuthenticator.CuSec); SignedCms signed = new SignedCms( new ContentInfo( IdPkInitAuthData, authPack.Encode().ToArray() ) ); var signer = new CmsSigner(Certificate) { IncludeOption = IncludeOption }; signed.ComputeSignature(signer, silent: true); var pk = new KrbPaPkAsReq { SignedAuthPack = signed.Encode() }; padata.Add(new KrbPaData { Type = PaDataType.PA_PK_AS_REQ, Value = pk.Encode() }); req.PaData = padata.ToArray(); }
public void ParsePaPkAsReq_SignedAuthPack() { KrbPaPkAsReq asreq = KrbPaPkAsReq.Decode(signedPkAsReq); SignedCms signedCms = new SignedCms(); signedCms.Decode(asreq.SignedAuthPack.ToArray()); signedCms.CheckSignature(verifySignatureOnly: true); }
public override void TransformKdcReq(KrbKdcReq req) { var padata = req.PaData.ToList(); KrbAuthPack authPack; if (SupportsEllipticCurveDiffieHellman) { authPack = CreateEllipticCurveDiffieHellmanAuthPack(req.Body); } else if (SupportsDiffieHellman) { authPack = CreateDiffieHellmanAuthPack(req.Body); } else { throw OnlyKeyAgreementSupportedException(); } KerberosConstants.Now(out authPack.PKAuthenticator.CTime, out authPack.PKAuthenticator.CuSec); SignedCms signed = new SignedCms( new ContentInfo( IdPkInitAuthData, authPack.Encode().ToArray() ) ); var signer = new CmsSigner(Certificate) { IncludeOption = IncludeOption }; signed.ComputeSignature(signer, silent: true); var pk = new KrbPaPkAsReq { SignedAuthPack = signed.Encode() }; padata.Add(new KrbPaData { Type = PaDataType.PA_PK_AS_REQ, Value = pk.Encode() }); req.PaData = padata.ToArray(); }
public override async Task <KrbPaData> Validate(KrbKdcReq asReq, PreAuthenticationContext preauth) { var paPk = asReq.PaData.FirstOrDefault(p => p.Type == PaDataType.PA_PK_AS_REQ); if (paPk == null) { return(null); } var pkreq = KrbPaPkAsReq.Decode(paPk.Value); var authPack = await ValidateAuthPack(preauth.Principal, pkreq); ValidateAuthenticator(authPack.PKAuthenticator, asReq.Body); var requestAlg = authPack.ClientPublicValue?.Algorithm?.Algorithm; IKeyAgreement agreement; if (requestAlg?.Value == EllipticCurveDiffieHellman.Value) { agreement = FromEllipticCurveDomainParameters(authPack.ClientPublicValue); } else if (requestAlg?.Value == DiffieHellman.Value) { agreement = await FromDiffieHellmanDomainParametersAsync(authPack.ClientPublicValue); } else { throw OnlyKeyAgreementSupportedException(); } var derivedKey = agreement.GenerateAgreement(); var etype = asReq.Body.EType.First(); var transform = CryptoService.CreateTransform(etype); ReadOnlyMemory <byte> clientDHNonce = authPack.ClientDHNonce.GetValueOrDefault(); ReadOnlyMemory <byte> serverDHNonce = default; if (clientDHNonce.Length > 0) { serverDHNonce = transform.GenerateRandomBytes(agreement.PublicKey.KeyLength); await Service.Principals.CacheKey(agreement.PrivateKey); } var keyInfo = new KrbKdcDHKeyInfo { SubjectPublicKey = agreement.PublicKey.EncodePublicKey() }; if (agreement.PublicKey.CacheExpiry.HasValue) { keyInfo.DHKeyExpiration = agreement.PublicKey.CacheExpiry; keyInfo.Nonce = authPack.PKAuthenticator.Nonce; } var sessionKey = PKInitString2Key.String2Key( derivedKey.Span, transform.KeySize, clientDHNonce.Span, serverDHNonce.Span ); var paPkRep = new KrbPaPkAsRep { DHInfo = new KrbDHReplyInfo { DHSignedData = await SignDHResponseAsync(keyInfo), ServerDHNonce = serverDHNonce } }; preauth.PaData = new[] { new KrbPaData { Type = PaDataType.PA_PK_AS_REP, Value = paPkRep.Encode() } }; preauth.EncryptedPartKey = new KerberosKey(key: sessionKey.ToArray(), etype: etype); return(null); }
private static async Task <KrbAuthPack> ValidateAuthPack(IKerberosPrincipal principal, KrbPaPkAsReq pkreq) { SignedCms signedCms = new SignedCms(); signedCms.Decode(pkreq.SignedAuthPack.ToArray()); signedCms.CheckSignature(verifySignatureOnly: true); await principal.Validate(signedCms.Certificates); var authPack = KrbAuthPack.Decode(signedCms.ContentInfo.Content); return(authPack); }
/// <summary> /// Applies credential-specific changes to the KDC-REQ message and is what supplies the PKINIT properties to the request. /// </summary> /// <param name="req">The <see cref="KrbKdcReq"/> that will be modified.</param> public override void TransformKdcReq(KrbKdcReq req) { if (req == null) { throw new ArgumentNullException(nameof(req)); } this.agreement = this.StartKeyAgreement(); // We don't support the straight RSA mode because // it doesn't rely on ephemeral key agreement // which isn't great security-wise if (this.agreement == null) { throw OnlyKeyAgreementSupportedException(); } var padata = req.PaData.ToList(); KrbAuthPack authPack; if (this.SupportsEllipticCurveDiffieHellman) { authPack = this.CreateEllipticCurveDiffieHellmanAuthPack(req.Body); } else if (this.SupportsDiffieHellman) { authPack = this.CreateDiffieHellmanAuthPack(req.Body); } else { throw OnlyKeyAgreementSupportedException(); } Now(out DateTimeOffset ctime, out int usec); authPack.PKAuthenticator.CTime = ctime; authPack.PKAuthenticator.CuSec = usec; SignedCms signed = new SignedCms( new ContentInfo( IdPkInitAuthData, authPack.Encode().ToArray() ) ); var signer = new CmsSigner(this.Certificate) { IncludeOption = this.IncludeOption }; signed.ComputeSignature(signer, silent: !CanPrompt); var pk = new KrbPaPkAsReq { SignedAuthPack = signed.Encode() }; padata.Add(new KrbPaData { Type = PaDataType.PA_PK_AS_REQ, Value = pk.Encode() }); req.PaData = padata.ToArray(); }
public void ParsePaPkAsReq() { KrbPaPkAsReq asreq = KrbPaPkAsReq.Decode(signedPkAsReq); Assert.IsNotNull(asreq); }