private static bool ReadFixedData(ref ArrayOffset <byte> input, int length, out byte[] data) { if (input.Length < length) { data = null; return(false); } data = new byte[length]; input.CopyTo(data, 0, length); input += length; return(true); }
public static IList <SctSignature> DecodeData(byte[] rawData) { var signatures = new List <SctSignature>(); var rData = new ArrayOffset <byte>(rawData, 0); ArrayOffset <byte> list; if (!ReadChunkUInt16Header(ref rData, out list)) { return(signatures); } ArrayOffset <byte> sct; int index = 0; while (ReadChunkUInt16Header(ref list, out sct)) { var originalSct = sct; SctVersion version; byte[] logId; DateTime timestamp; byte[] extensions; SctHashAlgorithm hashAlgorithm; SctSignatureAlgorithm signatureAlgorithm; byte[] signature; if ( !ReadByteEnumeration(ref sct, out version) || !ReadFixedData(ref sct, LOG_ID_SIZE, out logId) || !ReadTimestamp(ref sct, out timestamp) || !ReadVariableDataUInt16Header(ref sct, out extensions) || !ReadByteEnumeration(ref sct, out hashAlgorithm) || !ReadByteEnumeration(ref sct, out signatureAlgorithm) || !ReadVariableDataUInt16Header(ref sct, out signature) ) { continue; } signatures.Add(new SctSignature { LogId = logId, Timestamp = timestamp, HashAlgorithm = hashAlgorithm, SignatureAlgorithm = signatureAlgorithm, Extensions = extensions, Signature = signature, Index = index++ }); } return(signatures); }
private static bool ReadTimestamp(ref ArrayOffset <byte> input, out DateTime timestamp) { const int size = sizeof(ulong); if (input.Length < size) { timestamp = default(DateTime); return(false); } var epochTime = 0UL; for (int i = 0, shift = size - 1; i < size; i++, shift--) { epochTime |= ((ulong)input[i] << (shift * 8)); } timestamp = Epoch.UNIX_EPOCH.AddMilliseconds(epochTime); input += size; return(true); }
private static bool ReadByteEnumeration <TEnumType>(ref ArrayOffset <byte> input, out TEnumType value) { if (!typeof(TEnumType).IsEnum || typeof(TEnumType).GetEnumUnderlyingType() != typeof(byte)) { throw new ArgumentException(nameof(TEnumType)); } const int size = sizeof(byte); if (input.Length < size) { value = default(TEnumType); return(false); } var val = input[0]; value = (TEnumType)(object)val; input += size; return(true); }
private static bool ReadChunkUInt16Header(ref ArrayOffset <byte> input, out ArrayOffset <byte> output) { var inputCopy = input; const int headerSize = sizeof(ushort); if (inputCopy.Length < headerSize) { output = default(ArrayOffset <byte>); return(false); } var chunkSize = (ushort)(inputCopy[0] << 8 | inputCopy[1]); //TLS records are big endian. if (chunkSize > inputCopy.Length - headerSize) { output = default(ArrayOffset <byte>); return(false); } var amountToConsume = headerSize + chunkSize; output = inputCopy + headerSize; input += amountToConsume; return(true); }
private static bool ReadVariableDataUInt16Header(ref ArrayOffset <byte> input, out byte[] data) { const int headerSize = sizeof(ushort); if (input.Length < headerSize) { data = null; return(false); } var chunkSize = (ushort)(input[0] << 8 | input[1]); //Big endian read input += headerSize; if (chunkSize == 0) { data = new byte[0]; return(true); } var result = new byte[chunkSize]; input.CopyTo(result, 0, chunkSize); input += chunkSize; data = result; return(true); }