Ejemplo n.º 1
0
        private Stream CreateXTSStream(File file, long?start = null, long?end = null)
        {
            var pub = CryptoUtil.GetCryptoPublicInfo(_cloud, file);
            var key = CryptoUtil.GetCryptoKey(_cloud.Account.Credentials.PasswordCrypt, pub.Salt);
            var xts = XtsAes256.Create(key, pub.IV);

            long fileLength      = file.OriginalSize;
            long requestedOffset = start ?? 0;
            long requestedEnd    = end ?? fileLength;

            long alignedOffset = requestedOffset / XTSSectorSize * XTSSectorSize;
            long alignedEnd    = requestedEnd % XTSBlockSize == 0
                ? requestedEnd
                : (requestedEnd / XTSBlockSize + 1) * XTSBlockSize;

            if (alignedEnd == 0)
            {
                alignedEnd = 16;
            }

            var downStream = _cloud.Account.RequestRepo.GetDownloadStream(file, alignedOffset, alignedEnd);

            ulong startSector = (ulong)alignedOffset / XTSSectorSize;
            int   trimStart   = (int)(requestedOffset - alignedOffset);
            uint  trimEnd     = alignedEnd == fileLength
                ? file.ServiceInfo.CryptInfo.AlignBytes
                : (uint)(alignedEnd - requestedEnd);

            var xtsStream = new XTSReadOnlyStream(downStream, xts, XTSSectorSize, startSector, trimStart, trimEnd);

            return(xtsStream);
        }
        private Stream GetCryptoStream(File file, FileUploadedDelegate onUploaded)
        {
            var info = CryptoUtil.GetCryptoKeyAndSalt(_cloud.Account.Credentials.PasswordCrypt);
            var xts  = XtsAes256.Create(info.Key, info.IV);

            file.ServiceInfo.CryptInfo = new CryptInfo
            {
                PublicKey = new CryptoKeyInfo {
                    Salt = info.Salt, IV = info.IV
                },
                AlignBytes = (uint)(file.Size % XTSWriteOnlyStream.BlockSize != 0
                    ? XTSWriteOnlyStream.BlockSize - file.Size % XTSWriteOnlyStream.BlockSize
                    : 0)
            };

            var size = file.OriginalSize % XTSWriteOnlyStream.BlockSize == 0
                ? file.OriginalSize.DefaultValue
                : (file.OriginalSize / XTSWriteOnlyStream.BlockSize + 1) * XTSWriteOnlyStream.BlockSize;

            var ustream = new SplittedUploadStream(file.FullPath, _cloud, size, false, file.ServiceInfo.CryptInfo);

            if (onUploaded != null)
            {
                ustream.FileUploaded += onUploaded;
            }
            // ReSharper disable once RedundantArgumentDefaultValue
            var encustream = new XTSWriteOnlyStream(ustream, xts, XTSWriteOnlyStream.DefaultSectorSize);

            return(encustream);
        }
Ejemplo n.º 3
0
        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();
        }