private void ReadHeaderV1(BinaryReader br) { header = new HeaderV1(); header.magic = new string(br.ReadChars(4)); header.type = br.ReadUInt32(); header.width = br.ReadUInt32(); header.height = br.ReadUInt32(); header.unk1 = br.ReadUInt32(); header.unk2 = br.ReadUInt32(); header.mips = br.ReadUInt32(); header.format = br.ReadUInt32(); }
protected internal Header GenerateHeader( ISymmetricEncryptionProviderOptions options, ReadOnlySpan <byte> symmetricKey = default, ReadOnlySpan <byte> privateKey = default, ReadOnlySpan <byte> metadata = default, IEncryptionProvider symmetricKeyEncryptionProvider = null) { Check.NotNull(nameof(options), options); privateKey = !privateKey.IsEmpty ? privateKey : options.Key.Memory.Span; ReadOnlySpan <byte> signingKey = default; if (options.SigningKey != null) { signingKey = options.SigningKey.Memory.Span; } // header values // 1. version // 2. metadataSize // 3. iterations // 4. symmetricSaltSize // 5. signingSaltSize // 6. ivSize // 7. symmetricKeySize // 8. hashSize // header values // 1. metadata (optional) // 2. symmetricSalt (optional) // 3. signingSalt (optional) // 4. iv // 5. symmetricKey (optional) // 6. hash var header = new HeaderV1(); header.MetaDataSize = metadata.Length; bool privateKeyEmpty = privateKey == null || privateKey.IsEmpty; bool symmetricKeyEmpty = symmetricKey == null || symmetricKey.IsEmpty; if (privateKeyEmpty && symmetricKeyEmpty) { throw new ArgumentNullException(nameof(privateKey), "privateKey or symmetricKey must have a value"); } if (!options.SkipSigning && privateKeyEmpty && signingKey.IsEmpty) { throw new ArgumentNullException(nameof(privateKey), "privateKey must have a value or options.SigningKey must have a value or options.SkipSigning must be true"); } if (!privateKeyEmpty) { header.SymmetricSaltSize = (short)(options.SaltSize / 8); if (!options.SkipSigning && (signingKey == null || signingKey.IsEmpty)) { header.SigningSaltSize = (short)(options.SaltSize / 8); this.signingAlgorithm = this.signingAlgorithm ?? CreateSigningAlgorithm(options); } } if (!symmetricKeyEmpty) { header.SymmetricKeySize = (short)(options.KeySize / 8); } this.algorithm = this.algorithm ?? CreateSymmetricAlgorithm(options); this.algorithm.GenerateIV(); var iv = this.algorithm.IV; header.IvSize = (short)iv.Length; { var buffer = MemoryPool <byte> .Shared.Rent(iv.Length); iv.CopyTo(buffer.Memory.Span); header.IV = buffer; } header.HashSize = (short)(this.signingAlgorithm.HashSize / 8); header.Iterations = options.Iterations; using (var ms = new MemoryStream(new byte[header.HeaderSize])) using (var bw = new BinaryWriter(ms, Utf8.NoBom, false)) { if (!symmetricKey.IsEmpty && symmetricKeyEncryptionProvider != null) { symmetricKey = symmetricKeyEncryptionProvider.Encrypt(symmetricKey); header.SymmetricKeySize = (short)symmetricKey.Length; } header.SymmetricAlgorithmType = options.SymmetricAlgorithm; header.KeyedHashAlgorithmType = options.KeyedHashedAlgorithm; bw.Write(header.Version); bw.Write((short)header.SymmetricAlgorithmType); bw.Write((short)header.KeyedHashAlgorithmType); bw.Write(header.MetaDataSize); bw.Write(header.Iterations); bw.Write(header.SymmetricSaltSize); bw.Write(header.SigningSaltSize); bw.Write(header.IvSize); bw.Write(header.SymmetricKeySize); bw.Write(header.HashSize); if (privateKey != null) { ReadOnlySpan <byte> symmetricSalt = GenerateSalt(header.SymmetricSaltSize); if (symmetricSalt.Length != header.SymmetricSaltSize) { throw new Exception("bad length"); } using (var generator = new Rfc2898DeriveBytes(privateKey, symmetricSalt, options.Iterations, HashAlgorithmName.SHA256)) { //symmetricSalt = generator.Salt; ReadOnlySpan <byte> bytes = generator.GetBytes(options.KeySize / 8); var buffer = MemoryPool <byte> .Shared.Rent(bytes.Length); bytes.CopyTo(buffer.Memory.Span); header.SymmetricKey = buffer; bw.Write(symmetricSalt); } if (!options.SkipSigning || !signingKey.IsEmpty) { var signingSalt = GenerateSalt(header.SigningSaltSize); using (var generator = new Rfc2898DeriveBytes( privateKey, signingSalt, options.Iterations, HashAlgorithmName.SHA256)) { signingKey = generator.GetBytes(options.KeySize / 8); var buffer = MemoryPool <byte> .Shared.Rent(signingKey.Length); signingKey.CopyTo(buffer.Memory.Span); header.SigningKey = buffer; bw.Write(signingSalt); } signingSalt.Clear(); } } bw.Write(iv); if (!symmetricKeyEmpty) { bw.Write(symmetricKey); } bw.Flush(); ms.Flush(); header.Position = ms.Position; ReadOnlySpan <byte> data = ms.ToArray(); header.Bytes = MemoryPool <byte> .Shared.Rent(header.HeaderSize); data.CopyTo(header.Bytes.Memory.Span); } return(header); }
protected internal Header ReadHeader( Stream reader, ISymmetricEncryptionProviderOptions options, ReadOnlySpan <byte> privateKey = default, IEncryptionProvider symmetricKeyEncryptionProvider = null) { Check.NotNull(nameof(reader), reader); Check.NotNull(nameof(options), options); ReadOnlySpan <byte> signingKey = default; if (options.SigningKey != null) { signingKey = options.SigningKey.Memory.Span; } using (var ms = new MemoryStream()) using (var bw = new BinaryWriter(ms, Utf8.NoBom, true)) using (var br = new BinaryReader(reader, Utf8.NoBom, true)) { var version = br.ReadInt16(); bw.Write(version); Header header = null; switch (version) { case 1: default: header = new HeaderV1(); break; } // header shorts/ints // 1. version // 2. algo // 3. signing, // 4. metadataSize // 5 iterations // 6. symmetricSaltSize // 7. signingSaltSize // 8. ivSize // 9. symmetricKeySize // 10. hashSize // header values // 1. metadata // 2. symmetricSalt // 3. signingSalt // 4. iv // 5. symmetricKey // 6. hash header.SymmetricAlgorithmType = (SymmetricAlgorithmType)br.ReadInt16(); header.KeyedHashAlgorithmType = (KeyedHashAlgorithmType)br.ReadInt16(); header.MetaDataSize = br.ReadInt32(); header.Iterations = br.ReadInt32(); header.SymmetricSaltSize = br.ReadInt16(); header.SigningSaltSize = br.ReadInt16(); header.IvSize = br.ReadInt16(); header.SymmetricKeySize = br.ReadInt16(); header.HashSize = br.ReadInt16(); bw.Write((short)header.SymmetricAlgorithmType); bw.Write((short)header.KeyedHashAlgorithmType); bw.Write(header.MetaDataSize); bw.Write(header.Iterations); bw.Write(header.SymmetricSaltSize); bw.Write(header.SigningSaltSize); bw.Write(header.IvSize); bw.Write(header.SymmetricKeySize); bw.Write(header.HashSize); if (options.SymmetricAlgorithm != header.SymmetricAlgorithmType) { options.SymmetricAlgorithm = header.SymmetricAlgorithmType; this.algorithm = null; } if (options.KeyedHashedAlgorithm != header.KeyedHashAlgorithmType) { options.KeyedHashedAlgorithm = header.KeyedHashAlgorithmType; this.signingAlgorithm = null; } byte[] metadata = null; byte[] symmetricSalt = null; ReadOnlySpan <byte> signingSalt = default; byte[] iv = null; ReadOnlySpan <byte> symmetricKey = default; byte[] hash = null; if (header.MetaDataSize > 0) { metadata = br.ReadBytes(header.MetaDataSize); bw.Write(metadata); } if (header.SymmetricSaltSize > 0) { symmetricSalt = br.ReadBytes(header.SymmetricSaltSize); bw.Write(symmetricSalt); } if (header.SigningSaltSize > 0) { signingSalt = br.ReadBytes(header.SigningSaltSize); bw.Write(signingSalt); } if (header.IvSize > 0) { iv = br.ReadBytes(header.IvSize); bw.Write(iv); } if (header.SymmetricKeySize > 0) { symmetricKey = br.ReadBytes(header.SymmetricKeySize); bw.Write(symmetricKey); } if (header.HashSize > 0) { hash = br.ReadBytes(header.HashSize); bw.Write(hash); } bw.Flush(); ms.Flush(); { var bytes = ms.ToArray(); var buffer = MemoryPool <byte> .Shared.Rent(bytes.Length); bytes.CopyTo(buffer.Memory.Span); header.Bytes = buffer; } header.Position = reader.Position; if (symmetricKeyEncryptionProvider != null) { symmetricKey = symmetricKeyEncryptionProvider.Decrypt(symmetricKey); } if (symmetricKey == null && privateKey.IsEmpty) { throw new ArgumentNullException(nameof(privateKey), "privateKey or symmetricKey must have a value"); } if (!options.SkipSigning && privateKey == null && signingKey.IsEmpty) { throw new ArgumentNullException(nameof(privateKey), "privateKey must have a value or options.SigningKey must have a value or options.SkipSigning must be true"); } if (symmetricKey == null) { if (symmetricSalt == null) { throw new InvalidOperationException("symmetricSalt for the privateKey could not be retrieved"); } using (var generator = new Rfc2898DeriveBytes(privateKey, symmetricSalt, header.Iterations, HashAlgorithmName.SHA256)) { var buffer = MemoryPool <byte> .Shared.Rent(options.KeySize / 8); ReadOnlySpan <byte> bytes = generator.GetBytes(options.KeySize / 8); bytes.CopyTo(buffer.Memory.Span); header.SymmetricKey = buffer; } } if (!options.SkipSigning && (signingKey == null || signingKey.IsEmpty)) { if (signingSalt == null) { throw new InvalidOperationException("symmetricSalt for the privateKey could not be retrieved"); } var key = !symmetricKey.IsEmpty ? symmetricKey : privateKey; using (var generator = new Rfc2898DeriveBytes(key, signingSalt, header.Iterations, HashAlgorithmName.SHA256)) { generator.IterationCount = header.Iterations; var buffer = MemoryPool <byte> .Shared.Rent(options.KeySize / 8); ReadOnlySpan <byte> bytes = generator.GetBytes(options.KeySize / 8); bytes.CopyTo(buffer.Memory.Span); header.SigningKey = buffer; } } { IMemoryOwner <byte> buffer = null; if (header.SymmetricKeySize > 0) { buffer = MemoryPool <byte> .Shared.Rent(header.SymmetricKeySize); symmetricKey.CopyTo(buffer.Memory.Span); header.SymmetricKey = buffer; } buffer = MemoryPool <byte> .Shared.Rent(iv.Length); iv.CopyTo(buffer.Memory.Span); header.IV = buffer; buffer = MemoryPool <byte> .Shared.Rent(header.HashSize); hash.CopyTo(buffer.Memory.Span); header.Hash = buffer; } return(header); } }
public void ReadHeaderV1() { log.Debug("Reading ABF Header (v1)"); headerV1 = new HeaderV1(); headerV1.fFileSignature = FileReadString(0, 4); //4s; headerV1.fFileVersionNumber = FileReadFloat(4, 1); //f; headerV1.nOperationMode = FileReadShort(8, 1); //h; headerV1.lActualAcqLength = FileReadInt(10, 1); //i; headerV1.nNumPointsIgnored = FileReadShort(14, 1); //h; headerV1.lActualEpisodes = FileReadInt(16, 1); //i; headerV1.lFileStartTime = FileReadInt(24, 1); //i; headerV1.lDataSectionPtr = FileReadInt(40, 1); //i; headerV1.lTagSectionPtr = FileReadInt(44, 1); //i; headerV1.lNumTagEntries = FileReadInt(48, 1); //i; headerV1.lSynchArrayPtr = FileReadInt(92, 1); //i; headerV1.lSynchArraySize = FileReadInt(96, 1); //i; headerV1.nDataFormat = FileReadShort(100, 1); //h; headerV1.nADCNumChannels = FileReadShort(120, 1); //h; headerV1.fADCSampleInterval = FileReadFloat(122, 1); //f; headerV1.fSynchTimeUnit = FileReadFloat(130, 1); //f; headerV1.lNumSamplesPerEpisode = FileReadInt(138, 1); //i; headerV1.lPreTriggerSamples = FileReadInt(142, 1); //i; headerV1.lEpisodesPerRun = FileReadInt(146, 1); //i; headerV1.fADCRange = FileReadFloat(244, 1); //f; headerV1.lADCResolution = FileReadInt(252, 1); //i; headerV1.nFileStartMillisecs = FileReadShort(366, 1); //h; headerV1.nADCPtoLChannelMap = FileReadShorts(378, 16); //16h; headerV1.nADCSamplingSeq = FileReadShorts(410, 16); //16h; headerV1.sADCChannelName = FileReadStrings(442, 10, 16); //10s; headerV1.sADCUnits = FileReadStrings(602, 8, 16); //8s; headerV1.fADCProgrammableGain = FileReadFloats(730, 16); //16f; headerV1.fInstrumentScaleFactor = FileReadFloats(922, 16); //16f; headerV1.fInstrumentOffset = FileReadFloats(986, 16); //16f; headerV1.fSignalGain = FileReadFloats(1050, 16); //16f; headerV1.fSignalOffset = FileReadFloats(1114, 16); //16f; headerV1.nDigitalEnable = FileReadShort(1436, 1); //h; headerV1.nActiveDACChannel = FileReadShort(1440, 1); //h; headerV1.nDigitalHolding = FileReadShort(1584, 1); //h; headerV1.nDigitalInterEpisode = FileReadShort(1586, 1); //h; headerV1.nDigitalValue = FileReadShorts(2588, 10); //10h; headerV1.lDACFilePtr = FileReadInts(2048, 2); //2i; headerV1.lDACFileNumEpisodes = FileReadInts(2056, 2); //2i; headerV1.fDACCalibrationFactor = FileReadFloats(2074, 4); //4f; headerV1.fDACCalibrationOffset = FileReadFloats(2090, 4); //4f; headerV1.nWaveformEnable = FileReadShorts(2296, 2); //2h; headerV1.nWaveformSource = FileReadShorts(2300, 2); //2h; headerV1.nInterEpisodeLevel = FileReadShorts(2304, 2); //2h; headerV1.nEpochType = FileReadShorts(2308, 20); //20h; headerV1.fEpochInitLevel = FileReadFloats(2348, 20); //20f; headerV1.fEpochLevelInc = FileReadFloats(2428, 20); //20f; headerV1.lEpochInitDuration = FileReadInts(2508, 20); //20i; headerV1.lEpochDurationInc = FileReadInts(2588, 20); //20i; headerV1.nTelegraphEnable = FileReadShorts(4512, 16); //16h; headerV1.fTelegraphAdditGain = FileReadFloats(4576, 16); //16f; headerV1.sProtocolPath = FileReadString(4898, 384); //384s; // clean up adc and dac units for (int i = 0; i < headerV1.sADCUnits.Length; i++) { headerV1.sADCUnits[i] = headerV1.sADCUnits[i].Trim(); } for (int i = 0; i < headerV1.sADCChannelName.Length; i++) { headerV1.sADCChannelName[i] = headerV1.sADCChannelName[i].Trim(); } }