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;
                    }
                }
            }
        }
示例#3
0
        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);
            }
        }