Ejemplo n.º 1
0
        private static byte[] EncryptBytes(Vault_oooCryptoData crypto, byte[] bytes)
        {
            using (AesManaged aes = new AesManaged())
            {
                aes.Mode      = CipherMode.CBC;
                aes.KeySize   = AES_KEY_SIZE;
                aes.BlockSize = AES_BLOCK_SIZE;

                aes.Key = crypto.Key;
                aes.IV  = crypto.IV;

                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(crypto.Key, crypto.IV), CryptoStreamMode.Write))
                    {
                        cs.Write(bytes, 0, bytes.Length); // Write all bytes into the CryptoStream
                        cs.Close();
                        return(ms.ToArray());
                    }
                }
            }
        }
Ejemplo n.º 2
0
        public override UploadResult Upload(Stream stream, string fileName)
        {
            #region Calculating sizes

            long fileSize       = stream.Length;
            int  chunks         = (int)Math.Ceiling((double)fileSize / BYTE_CHUNK_SIZE);
            long fullUploadSize = 16; // 16 bytes header

            List <long> uploadSizes = new List <long>();
            uploadSizes.Add(0);
            LoopStartEnd((chunkStart, chunkEnd, i) =>
            {
                int chunkLength = chunkEnd - chunkStart;
                fullUploadSize += chunkLength + 16 - (chunkLength % 16);
                uploadSizes.Add(fullUploadSize);
            }, chunks, fileSize);

            #endregion

            string randomKey               = GenerateRandomKey();
            byte[] randomKeyBytes          = Encoding.UTF8.GetBytes(randomKey);
            Vault_oooCryptoData cryptoData = DeriveCryptoData(randomKeyBytes);

            #region Building filename

            byte[] fileNameBytes = Encoding.UTF8.GetBytes(fileName);
            string encryptedFileName;
            using (MemoryStream ms = new MemoryStream()) // Encrypting file name
            {
                ms.Write(cryptoData.Salt, 0, cryptoData.Salt.Length);
                byte[] encryptedFn = EncryptBytes(cryptoData, fileNameBytes);
                ms.Write(encryptedFn, 0, encryptedFn.Length);
                encryptedFileName = Helpers.BytesToHex(ms.ToArray());
            }
            string   bytesLengthHex = fullUploadSize.ToString("X4");                                  // To Hex
            DateTime expiryTime     = DateTime.UtcNow.AddDays(30);                                    // Defaults from the web client
            string   expiryTimeHex  = ((long)(expiryTime - ORIGIN_TIME).TotalSeconds).ToString("X4"); // Expiry date in UNIX seconds in hex
            string   fullFileName   = $"{expiryTimeHex}-b-{bytesLengthHex}-{encryptedFileName}".ToLower();

            #endregion

            Dictionary <string, string> requestHeaders = new Dictionary <string, string>();
            requestHeaders.Add("X-Get-Raw-File", "1");
            Dictionary <string, long> postRequestJson = new Dictionary <string, long>();
            postRequestJson.Add("chunks", chunks);
            postRequestJson.Add("fileLength", fullUploadSize);

            string            postResult = SendRequest(HttpMethod.POST, URLHelpers.CombineURL(APIURL, fullFileName), JsonConvert.SerializeObject(postRequestJson), RequestHelpers.ContentTypeJSON, requestHeaders);
            Vault_oooMetaInfo metaInfo   = JsonConvert.DeserializeObject <Vault_oooMetaInfo>(postResult);

            if (string.IsNullOrEmpty(metaInfo.UrlPathName))
            {
                throw new InvalidOperationException("No correct metaInfo returned");
            }

            #region Upload in chunks

            List <byte> dumpStash = new List <byte>();
            LoopStartEnd((chunkStart, chunkEnd, i) =>
            {
                int chunkLength   = chunkEnd - chunkStart;
                byte[] plainBytes = new byte[chunkLength];
                stream.Read(plainBytes, 0, chunkLength);

                byte[] encryptedBytes = EncryptBytes(cryptoData, plainBytes);

                int prependSize = 0;
                if (dumpStash.Count > 0)
                {
                    using (MemoryStream ms = new MemoryStream())
                    {
                        ms.Write(dumpStash.ToArray(), 0, dumpStash.Count);
                        ms.Write(encryptedBytes, 0, encryptedBytes.Length);
                        encryptedBytes = ms.ToArray();
                    }

                    prependSize = dumpStash.Count;
                    dumpStash.Clear();
                }

                if (encryptedBytes.Length + (i == 0 ? 16 : 0) > BYTE_CHUNK_SIZE) // 16 bytes for the salt header
                {
                    dumpStash.AddRange(encryptedBytes.Skip(BYTE_CHUNK_SIZE - (i == 0 ? 16 : 0)));
                    encryptedBytes = encryptedBytes.Take(BYTE_CHUNK_SIZE - (i == 0 ? 16 : 0)).ToArray();
                }

                using (MemoryStream ms = new MemoryStream())
                {
                    if (i == 0)
                    {
                        ms.Write(Encoding.UTF8.GetBytes("Salted__"), 0, 8);   // Write header
                        ms.Write(cryptoData.Salt, 0, cryptoData.Salt.Length); // 8 bytes
                        ms.Write(encryptedBytes, 0, encryptedBytes.Length);
                    }
                    else
                    {
                        ms.Write(encryptedBytes, 0, encryptedBytes.Length); // Write encrypted bytes
                    }

                    NameValueCollection headers = new NameValueCollection();
                    headers.Add("X-Get-Raw-File", "1");
                    int uploadChunkStart = (int)(uploadSizes[i] - prependSize);
                    headers.Add("X-Put-Chunk-Start", uploadChunkStart.ToString());
                    headers.Add("X-Put-Chunk-End", (uploadChunkStart + ms.Length).ToString());
                    headers.Add("X-Put-JWT", metaInfo.Token);

                    SendRequest(HttpMethod.PUT, URLHelpers.CombineURL(APIURL, metaInfo.UrlPathName), ms, "application/octet-stream", null, headers);
                }
            }, chunks, fileSize);

            #endregion

            UploadResult res = new UploadResult();
            res.IsURLExpected = true;
            res.URL           = URLHelpers.CombineURL(APIURL, metaInfo.UrlPathName) + "#" + randomKey; // Full url with the encryption key

            return(res);
        }