public Stream ToStream(RSAPrivateKey signingKey) { if (ReferenceEquals(EmptyMessage, this)) { return(Stream.Null); } // Next version's data-length Write(0); byte[] signature = signingKey.SignHash(_hash.FinalizeHash()); PrimitiveSerializer.Bytes.WriteTo(signature, _payload); //_verified = true; _hash.Close(); _payload.Close(); _protected.Position = 0; MemoryStream header = new MemoryStream(); WriteHeader(header); header.Position = 0; return(new CombinedStream(header, _protected)); }
/// <summary> /// Called to send a specific length of bytes to a server identified by serverKey. The transfer /// is a blocking call and returns on success or raises an exception. If Abort() is called durring /// the transfer, or if a ProgressChanged event handler raises the OperationCanceledException, the /// transfer is silently terminated and the method will return false. /// </summary> /// <param name="location">A string of up to 1024 bytes in length</param> /// <param name="length">The length in bytes to send from the stream</param> /// <param name="rawInput">The stream to read the data from</param> /// <returns>True if the file was successfully received by the server</returns> public bool Upload(string location, long length, Stream rawInput) { Guid transferId = Guid.NewGuid(); int maxMessageLength; // STEP 1: Send a NonceRequest, Create Salt sessionKey = BeginUpload(transferId, location, length, out maxMessageLength); // STEP 2: Send the data Hash fullHash; bool[] failed = new bool[1]; using (HashStream input = new HashStream(new SHA256Managed(), rawInput)) using (WorkQueue queue = new WorkQueue(LimitThreads)) { queue.OnError += (o, e) => { failed[0] = true; }; long pos = 0; while (pos < length && !failed[0] && !_abort.WaitOne(0, false)) { int len = (int)Math.Min(length - pos, maxMessageLength); byte[] buffer = new byte[len]; IOStream.Read(input, buffer, len); BytesToSend task = new BytesToSend(this, LimitThreads, transferId, sessionKey, location, pos, buffer); queue.Enqueue(task.Send); OnProgressChanged(location, pos, length); pos += len; } queue.Complete(true, failed[0] ? 5000 : 300000); fullHash = input.FinalizeHash();//hash of all data transferred } if (_abort.WaitOne(0, false)) { return(false); } Check.Assert <InvalidDataException>(failed[0] == false); // STEP 4: Complete the transfer CompleteUpload(transferId, sessionKey, location, fullHash); OnProgressChanged(location, length, length); return(true); }
public void TestHashStreamWrite() { Random r = new Random(); byte[][] test = new byte[][] { new byte[300], new byte[1], new byte[500], new byte[11], new byte[1], new byte[1000], }; using (HashStream hs = new HashStream(new SHA256Managed())) using (MemoryStream ms = new MemoryStream()) using (HashStream hsWrap = new HashStream(new SHA256Managed(), ms)) { Assert.IsTrue(hs.CanWrite); long len = 0; foreach (byte[] bytes in test) { len += bytes.Length; r.NextBytes(bytes); hsWrap.Write(bytes, 0, bytes.Length); hs.Write(bytes, 0, bytes.Length); } for (int i = 0; i < 5; i++) { len += 1; byte val = (byte)r.Next(255); hsWrap.WriteByte(val); hs.WriteByte(val); } Assert.AreEqual(len, ms.Position); Hash expect = Hash.SHA256(ms.ToArray()); Hash actual = hs.Close(); Assert.AreEqual(expect, actual); Assert.AreEqual(expect.ToArray(), actual.ToArray()); Assert.AreEqual(expect.ToString(), actual.ToString()); //wrapped test actual = hsWrap.FinalizeHash(); Assert.AreEqual(expect, actual); Assert.AreEqual(expect.ToArray(), actual.ToArray()); Assert.AreEqual(expect.ToString(), actual.ToString()); } }
public void TestHashStreamRead() { Random r = new Random(); byte[] bytes = new byte[1000]; r.NextBytes(bytes); using (HashStream hs = new HashStream(new SHA256Managed(), new MemoryStream(bytes))) { for (int i = 0; i < 5; i++) while (hs.Position < hs.Length) { hs.ReadByte(); int amt = r.Next(255); byte[] tmp = new byte[amt]; hs.Read(tmp, 0, tmp.Length); } Hash expect = Hash.SHA256(bytes); Hash actual = hs.FinalizeHash(); Assert.AreEqual(expect, actual); Assert.AreEqual(expect.ToArray(), actual.ToArray()); Assert.AreEqual(expect.ToString(), actual.ToString()); //still valid after FinalizeHash(); however, hash is restarted hs.Position = 0; IOStream.Read(hs, bytes.Length); actual = hs.FinalizeHash(); Assert.AreEqual(expect, actual); Assert.AreEqual(expect.ToArray(), actual.ToArray()); Assert.AreEqual(expect.ToString(), actual.ToString()); } }
/// <summary> /// Called to send a specific length of bytes to a server identified by serverKey. The transfer /// is a blocking call and returns on success or raises an exception. If Abort() is called durring /// the transfer, or if a ProgressChanged event handler raises the OperationCanceledException, the /// transfer is silently terminated and the method will return false. /// </summary> /// <param name="location">A string of up to 1024 bytes in length</param> /// <param name="length">The length in bytes to send from the stream</param> /// <param name="rawInput">The stream to read the data from</param> /// <returns>True if the file was successfully received by the server</returns> public bool Upload(string location, long length, Stream rawInput) { Guid transferId = Guid.NewGuid(); int maxMessageLength; // STEP 1: Send a NonceRequest, Create Salt sessionKey = BeginUpload(transferId, location, length, out maxMessageLength); // STEP 2: Send the data Hash fullHash; bool[] failed = new bool[1]; using (HashStream input = new HashStream(new SHA256Managed(), rawInput)) using (WorkQueue queue = new WorkQueue(LimitThreads)) { queue.OnError += (o, e) => { failed[0] = true; }; long pos = 0; while (pos < length && !failed[0] && !_abort.WaitOne(0, false)) { int len = (int)Math.Min(length - pos, maxMessageLength); byte[] buffer = new byte[len]; IOStream.Read(input, buffer, len); BytesToSend task = new BytesToSend(this, LimitThreads, transferId, sessionKey, location, pos, buffer); queue.Enqueue(task.Send); OnProgressChanged(location, pos, length); pos += len; } queue.Complete(true, failed[0] ? 5000 : 300000); fullHash = input.FinalizeHash();//hash of all data transferred } if (_abort.WaitOne(0, false)) return false; Check.Assert<InvalidDataException>(failed[0] == false); // STEP 4: Complete the transfer CompleteUpload(transferId, sessionKey, location, fullHash); OnProgressChanged(location, length, length); return true; }