public ContainerWriter(Stream writeStream, string fileName, X509Certificate2 certificate) { this.writeStream = writeStream ?? throw new ArgumentNullException(nameof(writeStream)); this.fileName = fileName ?? throw new ArgumentNullException(nameof(writeStream)); FileNameHelper.CheckFileName(fileName, nameof(fileName)); this.aes = new AesManaged(); this.aes.Mode = CipherMode.CBC; this.aes.Padding = PaddingMode.PKCS7; this.aes.KeySize = 256; this.aes.BlockSize = 128; this.randomSource = new Random(Guid.NewGuid().GetHashCode()); this.aes.GenerateKey(); this.aes.GenerateIV(); this.header = new ContainerHeader(); this.header.CertificateThumbprint = certificate.Thumbprint; this.header.EncryptedDataSize = 0L; this.header.KeyType = this.GetKeyType(certificate.GetRSAPublicKey()); this.header.EncryptedKey = certificate.GetRSAPublicKey().Encrypt(this.aes.Key, RSAEncryptionPadding.Pkcs1); //RSA Padding this.header.InitializeVector = this.aes.IV; this.encryptor = this.aes.CreateEncryptor(); this.headerWrited = false; this.AdditionalPadingSize = (uint)this.randomSource.Next(512, 2048); }
public async Task <string> ReadFileName() { if (this.fileName != null) { return(this.fileName); } ContainerHeader header = await ContainerHeader.ReadFromStream(this.readerStream); byte[]? aesKey = null; try { aesKey = await this.cryptoAccessor.AsymetricDecrypt(header.CertificateThumbprint, header.EncryptedKey, RSAEncryptionPadding.Pkcs1); //RSA Padding this.aesDecryptor = this.aes.CreateDecryptor(aesKey, header.InitializeVector); this.cryptoStream = new CryptoStream(this.readerStream, this.aesDecryptor, CryptoStreamMode.Read); using (BinaryDataStream bds = new BinaryDataStream(this.cryptoStream, false)) { //TODO: Optimalization for (uint i = 0; i < 16; i++) { bds.ReadByte(); } uint randomDataSize = await bds.Read4BitNumber(); uint stringLen = await bds.Read4BitNumber(); //TODO: Optimalization for (uint i = 0; i < randomDataSize; i++) { bds.ReadByte(); } string fileName = await bds.ReadConstatntString((int)stringLen, Encoding.UTF8); FileNameHelper.CheckFileName(fileName, nameof(fileName)); this.fileName = fileName; return(fileName); } } finally { if (aesKey != null) { for (int i = 0; i < aesKey.Length; i++) { aesKey[i] = 0x00; aesKey[i] = 0xFF; } } } }
public static async Task <ContainerHeader> ReadFromStream(Stream stream) { using (BinaryDataStream dataStream = new BinaryDataStream(stream, false)) { await CheckPrefix(dataStream); ContainerHeader header = new ContainerHeader(); header.Version = await dataStream.Read2BitNumber(); if (header.Version != DefaultVersion) { throw new InvalidOperationException($"Encryption file version {header.Version} is not supported."); } header.Reserved = await dataStream.Read4BitNumber(); header.KeyType = (ContainerKeyType)await dataStream.Read4BitNumber(); int encryptedKeySize = header.KeyType switch { ContainerKeyType.Rsa2048 => 256, ContainerKeyType.Rsa3072 => 384, ContainerKeyType.Rsa4096 => 512, _ => throw new NotSupportedException($"Not support key type {header.KeyType}") }; header.EncryptedDataSize = await dataStream.Read8BitNumber(); header.CertificateThumbprint = await dataStream.ReadConstatntString(40, Encoding.ASCII); header.EncryptedKey = new byte[encryptedKeySize]; header.InitializeVector = new byte[16]; await dataStream.ReadAsync(header.EncryptedKey, 0, header.EncryptedKey.Length); await dataStream.ReadAsync(header.InitializeVector, 0, header.InitializeVector.Length); return(header); } }