/// <summary> /// Calculate Server checksum (TD section 2.8.1) of the PAC message, /// place the checksum as a PacInfoBuffer whose ulType_Values is V3. /// Then calculate KDC checksum (TD section 2.8.2) of the PAC message, /// place the checksum as a PacInfoBuffer whose ulType_Values is V4. /// </summary> /// <param name="serverSignKey">The server signature key used to generate server signature.</param> /// <param name="kdcSignKey">The KDC signature key used to generate KDC signature.</param> /// <exception cref="ArgumentNullException">serverSignkey or kdcSignKey is null.</exception> public void Sign(byte[] serverSignKey, byte[] kdcSignKey) { // locate server and KDC signatures. PacSignatureData serverSign; PacSignatureData kdcSign; FindSignatures(out serverSign, out kdcSign); // types PAC_SIGNATURE_DATA_SignatureType_Values serversignType = serverSign.NativePacSignatureData.SignatureType; PAC_SIGNATURE_DATA_SignatureType_Values kdcSignType = kdcSign.NativePacSignatureData.SignatureType; // clear signatures. int serverLength = PacSignatureData.CalculateSignatureLength(serversignType); serverSign.NativePacSignatureData.Signature = new byte[serverLength]; int kdcLength = PacSignatureData.CalculateSignatureLength(kdcSignType); kdcSign.NativePacSignatureData.Signature = new byte[kdcLength]; // sign server byte[] serverSignResult = PacSignatureData.Sign( ToBytes(), serversignType, serverSignKey); serverSign.NativePacSignatureData.Signature = serverSignResult; // sign KDC kdcSign.NativePacSignatureData.Signature = PacSignatureData.Sign( serverSignResult, kdcSignType, kdcSignKey); }
/// <summary> /// Sign input plaintext bytes into checksum bytes. /// </summary> /// <param name="input">The specified plaintext bytes.</param> /// <param name="type">The specified checksum algorithm.</param> /// <param name="key">The specified key.</param> /// <returns>The signed checksum bytes.</returns> internal static byte[] Sign(byte[] input, PAC_SIGNATURE_DATA_SignatureType_Values type, byte[] key) { switch (type) { case PAC_SIGNATURE_DATA_SignatureType_Values.HMAC_SHA1_96_AES128: return(HmacSha1AesChecksum.GetMic( key, input, PacSignatureData.KerbNonKerbCksumSalt, AesKeyType.Aes128BitsKey)); case PAC_SIGNATURE_DATA_SignatureType_Values.HMAC_SHA1_96_AES256: return(HmacSha1AesChecksum.GetMic( key, input, PacSignatureData.KerbNonKerbCksumSalt, AesKeyType.Aes256BitsKey)); case PAC_SIGNATURE_DATA_SignatureType_Values.KERB_CHECKSUM_HMAC_MD5: return(HmacMd5StringChecksum.GetMic( key, input, PacSignatureData.KerbNonKerbCksumSalt)); default: throw new ArgumentOutOfRangeException("type"); } }
/// <summary> /// Calculate size of current instance's encoded buffer, in bytes. /// </summary> /// <returns>The size of current instance's encoded buffer, in bytes.</returns> internal override int CalculateSize() { PAC_SIGNATURE_DATA_SignatureType_Values type = NativePacSignatureData.SignatureType; // The structure contains following part: // SignatureType (4 bytes) // Signature (variable, calculated by SignatureType) return(sizeof(uint) + CalculateSignatureLength(type)); }
/// <summary> /// Creates an PacType instance using the specified signature types and PacInfoBuffers /// </summary> /// <param name="serverSignatureType">Server signature signatureType.</param> /// <param name="serverSignKey">The server signature key used to generate server signature.</param> /// <param name="kdcSignatureType">KDC signature Type.</param> /// <param name="kdcSignKey">The KDC signature key used to generate KDC signature.</param> /// <param name="pacInfoBuffers">A list of PacInfoBuffer used to create the PacType. /// Note: DO NOT include the signatures (server signature and KDC signature)!</param> /// <returns>The created PacType instance.</returns> public static PacType CreatePacType( PAC_SIGNATURE_DATA_SignatureType_Values serverSignatureType, byte[] serverSignKey, PAC_SIGNATURE_DATA_SignatureType_Values kdcSignatureType, byte[] kdcSignKey, params PacInfoBuffer[] pacInfoBuffers) { return(new PacType( serverSignatureType, serverSignKey, kdcSignatureType, kdcSignKey, pacInfoBuffers)); }
/// <summary> /// Calculate checksum length according to specified checksum type. /// </summary> /// <param name="signatureType">The specified checksum type.</param> /// <returns>The calculated checksum length.</returns> internal static int CalculateSignatureLength(PAC_SIGNATURE_DATA_SignatureType_Values signatureType) { switch (signatureType) { case PAC_SIGNATURE_DATA_SignatureType_Values.KERB_CHECKSUM_HMAC_MD5: return(KerbChecksumHmacMd5Size); case PAC_SIGNATURE_DATA_SignatureType_Values.HMAC_SHA1_96_AES128: return(KerbChecksumHmacSha1Size); case PAC_SIGNATURE_DATA_SignatureType_Values.HMAC_SHA1_96_AES256: return(KerbChecksumHmacSha1Size); default: throw new ArgumentOutOfRangeException("signatureType"); } }
/// <summary> /// Creates an PacType instance using the specified signature types and PacInfoBuffers /// </summary> /// <param name="serverSignatureType">Server signature signatureType.</param> /// <param name="serverSignKey">The server signature key used to generate server signature.</param> /// <param name="kdcSignatureType">KDC signature Type.</param> /// <param name="kdcSignKey">The KDC signature key used to generate KDC signature.</param> /// <param name="buffers">A list of PacInfoBuffer used to create the PacType. /// Note: DO NOT include the signatures (server signature and KDC signature)!</param> /// <returns>The created PacType instance.</returns> internal PacType( PAC_SIGNATURE_DATA_SignatureType_Values serverSignatureType, byte[] serverSignKey, PAC_SIGNATURE_DATA_SignatureType_Values kdcSignatureType, byte[] kdcSignKey, params PacInfoBuffer[] buffers) { if (buffers == null || buffers.Length == 0) { throw new ArgumentNullException("buffers"); } InitializePacInfoBuffers(serverSignatureType, kdcSignatureType, buffers); InitializeNativePacType(); Sign(serverSignKey, kdcSignKey); // after Sign(), the contentd of signature buffers are filled, // and the lengths of which are changed. // Then update interrelated fields, mainly totalLength and offset. UpdateInterrelatedFields(); }
/// <summary> /// In constructor, initialize the member PacInfoBuffer array. /// </summary> /// <param name="serverSignatureType">The specified /// Server Signature Type.</param> /// <param name="kdcSignatureType">The specified /// KDC Signature Type.</param> /// <param name="buffers">PacInfoBuffers not including signatures.</param> private void InitializePacInfoBuffers( PAC_SIGNATURE_DATA_SignatureType_Values serverSignatureType, PAC_SIGNATURE_DATA_SignatureType_Values kdcSignatureType, PacInfoBuffer[] buffers) { // allocate 2 more buffers for server signature and KDC signature. pacInfoBuffers = new PacInfoBuffer[buffers.Length + 2]; for (int i = 0; i < buffers.Length; i++) { pacInfoBuffers[i] = buffers[i]; } // construct a n empty server signature PacServerSignature serverSign = new PacServerSignature(); serverSign.NativePacSignatureData.SignatureType = serverSignatureType; serverSign.NativePacSignatureData.Signature = new byte[0]; pacInfoBuffers[pacInfoBuffers.Length - 2] = serverSign; // construct a n empty KDC signature PacKdcSignature kdcSign = new PacKdcSignature(); kdcSign.NativePacSignatureData.SignatureType = kdcSignatureType; kdcSign.NativePacSignatureData.Signature = new byte[0]; pacInfoBuffers[pacInfoBuffers.Length - 1] = kdcSign; }
/// <summary> /// Sign input plaintext bytes into checksum bytes. /// </summary> /// <param name="input">The specified plaintext bytes.</param> /// <param name="type">The specified checksum algorithm.</param> /// <param name="key">The specified key.</param> /// <returns>The signed checksum bytes.</returns> internal static byte[] Sign(byte[] input, PAC_SIGNATURE_DATA_SignatureType_Values type, byte[] key) { switch (type) { case PAC_SIGNATURE_DATA_SignatureType_Values.HMAC_SHA1_96_AES128: return HmacSha1AesChecksum.GetMic( key, input, PacSignatureData.KerbNonKerbCksumSalt, AesKeyType.Aes128BitsKey); case PAC_SIGNATURE_DATA_SignatureType_Values.HMAC_SHA1_96_AES256: return HmacSha1AesChecksum.GetMic( key, input, PacSignatureData.KerbNonKerbCksumSalt, AesKeyType.Aes256BitsKey); case PAC_SIGNATURE_DATA_SignatureType_Values.KERB_CHECKSUM_HMAC_MD5: return HmacMd5StringChecksum.GetMic( key, input, PacSignatureData.KerbNonKerbCksumSalt); default: throw new ArgumentOutOfRangeException("type"); } }
/// <summary> /// Calculate checksum length according to specified checksum type. /// </summary> /// <param name="signatureType">The specified checksum type.</param> /// <returns>The calculated checksum length.</returns> internal static int CalculateSignatureLength(PAC_SIGNATURE_DATA_SignatureType_Values signatureType) { switch (signatureType) { case PAC_SIGNATURE_DATA_SignatureType_Values.KERB_CHECKSUM_HMAC_MD5: return KerbChecksumHmacMd5Size; case PAC_SIGNATURE_DATA_SignatureType_Values.HMAC_SHA1_96_AES128: return KerbChecksumHmacSha1Size; case PAC_SIGNATURE_DATA_SignatureType_Values.HMAC_SHA1_96_AES256: return KerbChecksumHmacSha1Size; default: throw new ArgumentOutOfRangeException("signatureType"); } }
/// <summary> /// Verify Server checksum (TD section 2.8.1) and KDC checksum (TD section 2.8.2) /// of the PAC message. /// </summary> /// <param name="serverSignKey">The server signature key used to generate server signature.</param> /// <param name="kdcSignKey">The KDC signature key used to generate KDC signature.</param> /// <param name="isServerSignValid">true if server signature is valid.</param> /// <param name="isKdcSignValid">true if KDC signature is valid.</param> /// <exception cref="ArgumentNullException">serverSignkey or kdcSignKey is null.</exception> public void ValidateSign(byte[] serverSignKey, byte[] kdcSignKey, out bool isServerSignValid, out bool isKdcSignValid) { if (serverSignKey == null) { throw new ArgumentNullException("serverSignKey"); } if (kdcSignKey == null) { throw new ArgumentNullException("kdcSignKey"); } // locate server and KDC signatures. PacSignatureData serverSign; PacSignatureData kdcSign; FindSignatures(out serverSign, out kdcSign); // these validate operation will change signature values, so must backup and restore. byte[] oldServerSign = null; byte[] oldKdcSign = null; isServerSignValid = false; isKdcSignValid = false; try { // types PAC_SIGNATURE_DATA_SignatureType_Values serverSignType = serverSign.NativePacSignatureData.SignatureType; PAC_SIGNATURE_DATA_SignatureType_Values kdcSignType = kdcSign.NativePacSignatureData.SignatureType; // backup and clear signatures. int serverLength = PacSignatureData.CalculateSignatureLength(serverSignType); oldServerSign = serverSign.NativePacSignatureData.Signature; serverSign.NativePacSignatureData.Signature = new byte[serverLength]; int kdcLength = PacSignatureData.CalculateSignatureLength(kdcSignType); oldKdcSign = kdcSign.NativePacSignatureData.Signature; kdcSign.NativePacSignatureData.Signature = new byte[kdcLength]; // validate server sign byte[] serverSignResult = PacSignatureData.Sign( ToBytes(), serverSignType, serverSignKey); isServerSignValid = ArrayUtility.CompareArrays <byte>(serverSignResult, oldServerSign); // validate KDC sign byte[] kdcSignResult = PacSignatureData.Sign( serverSignResult, kdcSignType, kdcSignKey); isKdcSignValid = ArrayUtility.CompareArrays <byte>(kdcSignResult, oldKdcSign); } finally { // restore server signature if (oldServerSign != null) { serverSign.NativePacSignatureData.Signature = oldServerSign; } // restore KDC signature if (oldKdcSign != null) { kdcSign.NativePacSignatureData.Signature = oldKdcSign; } } }
internal static int CalculateSignatureLength(IEvaluationContext context) { PAC_SIGNATURE_DATA_SignatureType_Values signatureType = (PAC_SIGNATURE_DATA_SignatureType_Values)context.Variables["SignatureType"]; return(PacSignatureData.CalculateSignatureLength(signatureType)); }