public static void XTSEncrypt(SymmetricAlgorithm algorithm, byte[] key1, byte[] key2, ulong dataUnitIndex, byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { byte[] initializationVector = new byte[16]; ICryptoTransform encryptor1 = algorithm.CreateEncryptor(key1, initializationVector); ICryptoTransform encryptor2 = algorithm.CreateEncryptor(key2, initializationVector); XtsCryptoTransform transform = new XtsCryptoTransform(encryptor1, encryptor2, false); transform.TransformBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset, dataUnitIndex); }
public override void Write(byte[] buffer, int offset, int count) { ValidateSize(count); if (count == 0) { return; } var currentSector = CurrentSector; if (_encryptor == null) { _encryptor = _xts.CreateEncryptor(); } int transformedCount = _encryptor.TransformBlock(buffer, offset, count, _tempBuffer, 0, currentSector); base.Write(_tempBuffer, 0, transformedCount); }
public override int Read(byte[] buffer, int offset, int count) { ValidateSize(count); var currentSector = CurrentSector; var ret = base.Read(_tempBuffer, 0, count); if (ret == 0) { return(0); } if (_decryptor == null) { _decryptor = _xts.CreateDecryptor(); } var retV = _decryptor.TransformBlock(_tempBuffer, 0, ret, buffer, offset, currentSector); return(retV); }
protected override void TransformSectorImpl(Memory <byte> dest, ReadOnlyMemory <byte> src, long sectorNumber, bool logicalToPhysical) { checked { if (dest.Length != src.Length) { throw new ArgumentOutOfRangeException("dest.Length != src.Length"); } if (dest.Length != SectorSize) { throw new ArgumentOutOfRangeException("dest.Length != SectorSize"); } var destSeg = dest._AsSegment(); var srcSeg = src._AsSegment(); XtsCryptoTransform transform = logicalToPhysical ? this.CurrentDescrypter : this.CurrentEncrypter; transform.TransformBlock(srcSeg.Array !, srcSeg.Offset, srcSeg.Count, destSeg.Array !, destSeg.Offset, (ulong)sectorNumber); } }
protected override async Task InitMetadataImplAsync(CancellationToken cancel = default) { Memory <byte> firstSectorData = new byte[XtsAesMetaDataSize]; // ヘッダの読み込みを試行する int readSize = await this.PhysicalReadAsync(0, firstSectorData, cancel); if (readSize == XtsAesMetaDataSize) { var metaDataParseResult = TryParseMetaData(firstSectorData); metaDataParseResult.ThrowIfException(); var metaData = metaDataParseResult.Value !; // パスワード検査 if (Secure.VeritySaltedPassword(metaData.SaltedPassword, this.CurrentPassword) == false) { throw new CoresException("XtsAesRandomAccess: Incorrect password."); } // 秘密鍵解読 var decrypted = ChaChaPoly.EasyDecryptWithPassword(metaData.MasterKeyEncryptedByPassword._GetHexBytes(), this.CurrentPassword); decrypted.ThrowIfException(); // 秘密鍵サイズ検査 if (decrypted.Value.Length != XtsAesKeySize) { throw new CoresException("XtsAesRandomAccess: decrypted.Value.Length != XtsAesKeySize"); } this.CurrentMasterKey = decrypted.Value; this.CurrentMetaData = metaData; } else if (readSize == 0) { // ファイルの内容が存在しない // マスターキーを新規作成する this.CurrentMasterKey = Secure.Rand(XtsAesKeySize); // メタデータを新規作成する var metaData = new XtsAesRandomAccessMetaData { Version = 1, VirtualSize = 0, SaltedPassword = Secure.SaltPassword(this.CurrentPassword), MasterKeyEncryptedByPassword = ChaChaPoly.EasyEncryptWithPassword(this.CurrentMasterKey, this.CurrentPassword)._GetHexString(), }; this.CurrentMetaData = metaData; // メタデータを書き込みする await WriteMetaDataAsync(cancel); } else { // 不正 ここには来ないはず throw new CoresException($"XtsAesRandomAccess: Invalid readSize: {readSize}"); } // XTS を作成 this.CurrentXts = XtsAes256.Create(this.CurrentMasterKey.ToArray()); this.CurrentEncrypter = this.CurrentXts.CreateEncryptor(); this.CurrentDescrypter = this.CurrentXts.CreateDecryptor(); }