/// <summary> /// Decodes the object by PER. /// </summary> /// <param name="buffer">A buffer that contains a PER encoding result.</param> /// <param name="aligned">Indicating whether the PER decoding is aligned.</param> /// <remarks>Length is included.</remarks> protected override void ValuePerDecode(IAsn1DecodingBuffer buffer, bool aligned = true) { ByteArrayValue = Asn1StandardProcedure.PerDecodeArray <byte>(buffer, decodingBuffer => { Asn1Integer ai = new Asn1Integer(null, 0, 15); ai.PerDecode(buffer); if (Constraint == null || Constraint.PermittedCharSet == null) { if (ai.Value == 0) { return((byte)' '); } else if (ai.Value >= 1 && ai.Value <= 10) { return((byte)((byte)'0' + ai.Value - 1)); } else { throw new Asn1DecodingUnexpectedData(ExceptionMessages.DecodingUnexpectedData + "Only 0~9 and SPACE are allowed in NumericString."); } } else { int index = (int)ai.Value; return((byte)CharSetInArray[(int)ai.Value]); } }, Constraint != null && Constraint.HasMinSize ? Constraint.MinSize : (long?)null, Constraint != null && Constraint.HasMaxSize ? Constraint.MaxSize : (long?)null, true); }
//BER encoding/decoding are implemented in base class Asn1ByteString. #region PER /// <summary> /// Encodes the content of the object by PER. /// </summary> /// <param name="buffer">A buffer to which the encoding result will be written.</param> /// <remarks>Length is included.</remarks> protected override void ValuePerEncode(IAsn1PerEncodingBuffer buffer) { Asn1StandardProcedure.PerEncodeArray(buffer, Value.ToCharArray(), (encodingBuffer, b) => { int val; if (Constraint == null || Constraint.PermittedCharSet == null) { if (b == ' ') //SPACE->0000, '0'->0001, ..., '9'->1010 { val = 0; } else { val = 1 + b - '0'; } } else { for (val = 0; val != CharSetInArray.Length && b != CharSetInArray[val]; val++) { } } Asn1Integer ai = new Asn1Integer(val, 0, 15); ai.PerEncode(buffer); } , Constraint != null && Constraint.HasMinSize ? Constraint.MinSize : (long?)null, Constraint != null && Constraint.HasMaxSize ? Constraint.MaxSize : (long?)null, true); }
/// <summary> /// Decodes the object by PER. /// </summary> /// <param name="buffer">A buffer that contains a PER encoding result.</param> /// <param name="aligned">Indicating whether the PER decoding is aligned.</param> /// <remarks>Length is included.</remarks> protected override void ValuePerDecode(IAsn1DecodingBuffer buffer, bool aligned = true) { if (Constraint != null && Constraint.HasMinSize && Constraint.HasMinSize && Constraint.MinSize == Constraint.MaxSize && Constraint.MinSize <= 2) //Ref. X.691:16.6 { long minSize = Constraint.MinSize; bool[] bitResult = buffer.ReadBits((int)(8 * minSize)); byte[] byteResult = new byte[(int)minSize]; //Convert bool array to byte array int byteIndex = 0, bitIndex = 0; foreach (bool b in bitResult) { if (b) { byteResult[byteIndex] |= (byte)(1 << (7 - bitIndex)); } bitIndex++; if (bitIndex == 8) { bitIndex = 0; byteIndex++; } } ByteArrayValue = byteResult; } else { ByteArrayValue = Asn1StandardProcedure.PerDecodeArray(buffer, decodingBuffer => decodingBuffer.ReadByte(), Constraint != null && Constraint.HasMinSize ? Constraint.MinSize : (long?)null, Constraint != null && Constraint.HasMaxSize ? Constraint.MaxSize : (long?)null); } }
//BER encoding/decoding are implemented in base class Asn1ByteString. /// <summary> /// Encodes the content of the object by PER. /// </summary> /// <param name="buffer">A buffer to which the encoding result will be written.</param> /// <remarks>Length is included.</remarks> protected override void ValuePerEncode(IAsn1PerEncodingBuffer buffer) { if (Constraint != null && Constraint.HasMinSize && Constraint.HasMinSize && Constraint.MinSize == Constraint.MaxSize && Constraint.MinSize <= 2) //Ref. X.691:16.6 { buffer.WriteBits(ByteArrayValue, 0, ByteArrayValue.Length * 8); } else { Asn1StandardProcedure.PerEncodeArray(buffer, ByteArrayValue, (encodingBuffer, b) => { encodingBuffer.WriteByte(b); } , Constraint != null && Constraint.HasMinSize ? Constraint.MinSize : (long?)null, Constraint != null && Constraint.HasMaxSize ? Constraint.MaxSize : (long?)null); } }
private void DecryptAsResponse(byte[] key) { var encryptType = (EncryptionType)Response.enc_part.etype.Value; int keyUsage = (int)KeyUsageNumber.AS_REP_ENCRYPTEDPART; if (encryptType == EncryptionType.RC4_HMAC) { keyUsage = (int)KeyUsageNumber.TGS_REP_encrypted_part; } var encPartRawData = KerberosUtility.Decrypt( encryptType, key, Response.enc_part.cipher.ByteArrayValue, keyUsage); Asn1DecodingBuffer buf = new Asn1DecodingBuffer(encPartRawData); Asn1Tag tag = null; Asn1StandardProcedure.TagBerDecode(buf, out tag); //Some implementations unconditionally send an encrypted EncTGSRepPart in the field //regardless of whether the reply is an AS-REP or a TGS-REP.([RFC4120] Section 5.4.2) if (tag.TagValue == 25) //EncAsRepPart { EncPart = new EncASRepPart(); } else if (tag.TagValue == 26) //EncTgsRepPart { EncPart = new EncTGSRepPart(); } else { throw new Exception("Unknown tag number"); } EncPart.BerDecode(new Asn1DecodingBuffer(encPartRawData)); KerberosUtility.OnDumpMessage("KRB5:AS-REP(enc-part)", "Encrypted part of AS-REP", KerberosUtility.DumpLevel.PartialMessage, encPartRawData); }