示例#1
0
        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);
        }
示例#2
0
        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();
        }
示例#4
0
        public void ParsePaPkAsReq_SignedAuthPack()
        {
            KrbPaPkAsReq asreq = KrbPaPkAsReq.Decode(signedPkAsReq);

            SignedCms signedCms = new SignedCms();

            signedCms.Decode(asreq.SignedAuthPack.ToArray());
            signedCms.CheckSignature(verifySignatureOnly: true);
        }
示例#5
0
        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);
        }
示例#8
0
        /// <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();
        }
示例#9
0
        public void ParsePaPkAsReq()
        {
            KrbPaPkAsReq asreq = KrbPaPkAsReq.Decode(signedPkAsReq);

            Assert.IsNotNull(asreq);
        }