public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
 {
     if (!_writeMode)
     {
         _hmacsha1.TransformBlock(inputBuffer, inputOffset, inputCount, inputBuffer, inputOffset);
     }
     for (int i = 0; i < inputCount; i++)
     {
         if (_encrPos == 16)
         {
             int num = 0;
             while (++_counterNonce[num] == 0)
             {
                 num++;
             }
             _encryptor.TransformBlock(_counterNonce, 0, _blockSize, _encryptBuffer, 0);
             _encrPos = 0;
         }
         outputBuffer[i + outputOffset] = (byte)(inputBuffer[i + inputOffset] ^ _encryptBuffer[_encrPos++]);
     }
     if (_writeMode)
     {
         _hmacsha1.TransformBlock(outputBuffer, outputOffset, inputCount, outputBuffer, outputOffset);
     }
     return(inputCount);
 }
Beispiel #2
0
        // HKDF_SHA1
        // libsscrypto/hkdf.c mbedtls_hkdf
        public static byte[] GetAeadSubkey(byte[] key, byte[] salt, byte[] info, int outputLen)
        {
            byte[] prk;
            using (var h = new HMACSHA1(salt)) {
                prk = h.ComputeHash(key);
            }
            var N = outputLen / prk.Length;

            if (outputLen % prk.Length != 0)
            {
                N++;
            }
            var T      = new byte[0];
            var c      = new byte[1];
            var output = new byte[outputLen];
            var cur    = 0;

            using (var h = new HMACSHA1(prk)) {
                for (int i = 0; i < N; i++)
                {
                    h.TransformBlock(T, 0, T.Length, T, 0);
                    h.TransformBlock(info, 0, info.Length, info, 0);
                    c[0] = (byte)i;
                    T    = h.TransformFinalBlock(c, 0, 1);
                    NaiveUtils.CopyBytes(T, 0, output, cur, (i < N) ? T.Length : outputLen - cur);
                    cur += T.Length;
                }
            }
            return(output);
        }
 private void WriteTransformOneBlock(byte[] buffer, int offset)
 {
     Array.Copy(BitConverter.GetBytes(_nonce++), 0, counter, 0, 4);
     _xform.TransformBlock(counter, 0, 16, counterOut, 0);
     XorInPlace(buffer, offset, 16);
     _mac.TransformBlock(buffer, offset, 16, null, 0);
 }
Beispiel #4
0
 private void WriteTransformOneBlock(byte[] buffer, int offset)
 {
     System.Array.Copy(BitConverter.GetBytes(_nonce++), 0, counter, 0, 4);
     _xform.TransformBlock(counter,
                           0,
                           BLOCK_SIZE_IN_BYTES,
                           counterOut,
                           0);
     XorInPlace(buffer, offset, BLOCK_SIZE_IN_BYTES);
     _mac.TransformBlock(buffer, offset, BLOCK_SIZE_IN_BYTES, null, 0);
 }
Beispiel #5
0
 /// <summary>
 /// returns the hmac of the data and the annotation chunk values (except HMAC chunk itself)
 /// </summary>
 protected byte[] hmac()
 {
     using (HMACSHA1 hmac = new HMACSHA1(Config.HMAC_KEY)) {
         hmac.TransformBlock(this.data, 0, this.data.Length, this.data, 0);
         foreach (var e in this.annotations)
         {
             if (e.Key != "HMAC")
             {
                 hmac.TransformBlock(e.Value, 0, e.Value.Length, e.Value, 0);
             }
         }
         hmac.TransformFinalBlock(this.data, 0, 0);
         return(hmac.Hash);
     }
 }
Beispiel #6
0
 /// <summary>
 /// returns the hmac of the data and the annotation chunk values (except HMAC chunk itself)
 /// </summary>
 public byte[] hmac(byte[] key)
 {
     using (HMACSHA1 hmac = new HMACSHA1(key)) {
         hmac.TransformBlock(this.data, 0, this.data.Length, this.data, 0);
         foreach (var e in this.annotations.OrderBy(a => a.Key))
         {
             if (e.Key != "HMAC")
             {
                 hmac.TransformBlock(e.Value, 0, e.Value.Length, e.Value, 0);
             }
         }
         hmac.TransformFinalBlock(this.data, 0, 0);
         return(hmac.Hash);
     }
 }
        /// <summary>
        /// Decrypts using AES/CBC/PKCS7 with an input byte array and key, using the IV (comprised of random bytes and the HMAC-SHA1 of the random bytes and plaintext) prepended using AES/ECB/None
        /// </summary>
        public static byte[] SymmetricDecryptHMACIV(byte[] input, byte[] key, byte[] hmacSecret)
        {
            Debug.Assert(key.Length >= 16);
            var truncatedKeyForHmac = new byte[16];

            Array.Copy(key, 0, truncatedKeyForHmac, 0, truncatedKeyForHmac.Length);

            byte[] iv;
            var    plaintextData = SymmetricDecrypt(input, key, out iv);

            // validate HMAC
            byte[] hmacBytes;
            using (var hmac = new HMACSHA1(hmacSecret))
            {
                hmac.TransformBlock(iv, iv.Length - 3, 3, null, 0);
                hmac.TransformFinalBlock(plaintextData, 0, plaintextData.Length);

                hmacBytes = hmac.Hash;
            }

            if (!hmacBytes.Take(iv.Length - 3).SequenceEqual(iv.Take(iv.Length - 3)))
            {
                throw new CryptographicException(string.Format(CultureInfo.InvariantCulture, "{0} was unable to decrypt packet: HMAC from server did not match computed HMAC.", nameof(NetFilterEncryption)));
            }

            return(plaintextData);
        }
Beispiel #8
0
        /// <summary>
        /// Implement the ICryptoTransform method.
        /// </summary>
        public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer,
                                  int outputOffset)
        {
            // Pass the data stream to the hash algorithm for generating the Auth Code.
            // This does not change the inputBuffer. Do this before decryption for read mode.
            if (!_writeMode)
            {
#if !OS_WINDOWS
                incrementalHash.AppendData(inputBuffer, inputOffset, inputCount);
#else
                _hmacsha1.TransformBlock(inputBuffer, inputOffset, inputCount, inputBuffer, inputOffset);
#endif
            }
            // Encrypt with AES in CTR mode. Regards to Dr Brian Gladman for this.
            int ix = 0;
            while (ix < inputCount)
            {
                if (_encrPos == ENCRYPT_BLOCK)
                {
                    /* increment encryption nonce   */
                    int j = 0;
                    while (++_counterNonce[j] == 0)
                    {
                        ++j;
                    }
                    /* encrypt the nonce to form next xor buffer    */
                    _encryptor.TransformBlock(_counterNonce, 0, _blockSize, _encryptBuffer, 0);
                    _encrPos = 0;
                }
                outputBuffer[ix + outputOffset] = (byte)(inputBuffer[ix + inputOffset] ^ _encryptBuffer[_encrPos++]);
                //
                ix++;
            }
            if (_writeMode)
            {
                // This does not change the buffer.

#if !OS_WINDOWS
                incrementalHash.AppendData(outputBuffer, outputOffset, inputCount);
#else
                _hmacsha1.TransformBlock(outputBuffer, outputOffset, inputCount, outputBuffer, outputOffset);
#endif
            }
            return(inputCount);
        }
Beispiel #9
0
 public byte[] pyrohmac(byte[] data, IDictionary <string, byte[]> annotations)
 {
     using (HMACSHA1 hmac = new HMACSHA1(Config.HMAC_KEY)) {
         hmac.TransformBlock(data, 0, data.Length, data, 0);
         if (annotations != null)
         {
             foreach (var e in annotations)
             {
                 if (e.Key != "HMAC")
                 {
                     hmac.TransformBlock(e.Value, 0, e.Value.Length, e.Value, 0);
                 }
             }
         }
         hmac.TransformFinalBlock(data, 0, 0);
         return(hmac.Hash);
     }
 }
Beispiel #10
0
 public void CheckE(string testName, byte[] key, byte[] data, byte[] result)
 {
     algo = new HMACSHA1(key);
     byte[] copy = new byte [data.Length];
     // LAMESPEC or FIXME: TransformFinalBlock doesn't return HashValue !
     for (int i = 0; i < data.Length - 1; i++)
     {
         algo.TransformBlock(data, i, 1, copy, i);
     }
     algo.TransformFinalBlock(data, data.Length - 1, 1);
     Assert.AreEqual(result, algo.Hash, testName + "e");
 }
Beispiel #11
0
        public void GenerateSessionKey(byte[] clientSalt, byte[] serverSalt)
        {
            var hmac          = new HMACSHA1(SecureRemotePassword.SessionKey);
            var wow           = Encoding.ASCII.GetBytes("WoW\0");
            var wowSessionKey = new byte[0x28];

            hmac.TransformBlock(wow, 0, wow.Length, wow, 0);
            hmac.TransformBlock(clientSalt, 0, clientSalt.Length, clientSalt, 0);
            hmac.TransformFinalBlock(serverSalt, 0, serverSalt.Length);

            Buffer.BlockCopy(hmac.Hash, 0, wowSessionKey, 0, hmac.Hash.Length);

            hmac.Initialize();
            hmac.TransformBlock(wow, 0, wow.Length, wow, 0);
            hmac.TransformBlock(serverSalt, 0, serverSalt.Length, serverSalt, 0);
            hmac.TransformFinalBlock(clientSalt, 0, clientSalt.Length);

            Buffer.BlockCopy(hmac.Hash, 0, wowSessionKey, hmac.Hash.Length, hmac.Hash.Length);

            GameAccount.SessionKey = wowSessionKey.ToHexString();

            // Update SessionKey in database
            DB.Auth.Update(GameAccount, "SessionKey");
        }
Beispiel #12
0
 public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
 {
     if (!_writeMode)
     {
         _hmacsha1.TransformBlock(inputBuffer, inputOffset, inputCount, inputBuffer, inputOffset);
     }
     for (int i = 0; i < inputCount; i++)
     {
         if (_encrPos == ENCRYPT_BLOCK)
         {
             for (int j = 0; (_counterNonce[j] = (byte)(_counterNonce[j] + 1)) == 0; j++)
             {
             }
             _encryptor.TransformBlock(_counterNonce, 0, _blockSize, _encryptBuffer, 0);
             _encrPos = 0;
         }
         outputBuffer[i + outputOffset] = (byte)(inputBuffer[i + inputOffset] ^ _encryptBuffer[_encrPos++]);
     }
     if (_writeMode)
     {
         _hmacsha1.TransformBlock(outputBuffer, outputOffset, inputCount, outputBuffer, outputOffset);
     }
     return(inputCount);
 }
Beispiel #13
0
        /// <summary>
        /// Performs an encryption using AES/CBC/PKCS7 with an input byte array and key, with a IV (comprised of random bytes and the HMAC-SHA1 of the random bytes and plaintext) prepended using AES/ECB/None
        /// </summary>
        public static byte[] SymmetricEncryptWithHMACIV(byte[] input, byte[] key, byte[] hmacSecret)
        {
            // IV is HMAC-SHA1(Random(3) + Plaintext) + Random(3). (Same random values for both)
            var iv     = new byte[16];
            var random = GenerateRandomBlock(3);

            Array.Copy(random, 0, iv, iv.Length - random.Length, random.Length);

            using (var hmac = new HMACSHA1(hmacSecret))
            {
                hmac.TransformBlock(random, 0, random.Length, null, 0);
                hmac.TransformFinalBlock(input, 0, input.Length);
                Array.Copy(hmac.Hash, iv, iv.Length - random.Length);
            }

            return(SymmetricEncryptWithIV(input, key, iv));
        }
Beispiel #14
0
        private int ReadTransformOneBlock(byte[] buffer, int offset, int last)
        {
            if (_finalBlock)
            {
                throw new NotSupportedException();
            }

            int bytesRemaining = last - offset;
            int bytesToRead    = (bytesRemaining > BLOCK_SIZE_IN_BYTES)
                ? BLOCK_SIZE_IN_BYTES
                : bytesRemaining;

            // update the counter
            System.Array.Copy(BitConverter.GetBytes(_nonce++), 0, counter, 0, 4);

            // Determine if this is the final block
            if ((bytesToRead == bytesRemaining) &&
                (_length > 0) &&
                (_totalBytesXferred + last == _length))
            {
                _mac.TransformFinalBlock(buffer, offset, bytesToRead);
                counterOut = _xform.TransformFinalBlock(counter,
                                                        0,
                                                        BLOCK_SIZE_IN_BYTES);
                _finalBlock = true;
            }
            else
            {
                _mac.TransformBlock(buffer, offset, bytesToRead, null, 0);
                _xform.TransformBlock(counter,
                                      0, // offset
                                      BLOCK_SIZE_IN_BYTES,
                                      counterOut,
                                      0);  // offset
            }

            XorInPlace(buffer, offset, bytesToRead);
            return(bytesToRead);
        }
Beispiel #15
0
        // This function is defined as follow :
        // Func (S, i) = HMAC(S || i) | HMAC2(S || i) | ... | HMAC(iterations) (S || i)
        // where i is the block number.
        private byte[] Func()
        {
            byte[] INT_block = Int(m_block);

            m_hmacsha1.TransformBlock(m_salt, 0, m_salt.Length, m_salt, 0);
            m_hmacsha1.TransformFinalBlock(INT_block, 0, INT_block.Length);
            byte[] temp = m_hmacsha1.Hash;
            m_hmacsha1.Initialize();

            byte[] ret = temp;
            for (int i = 2; i <= m_iterations; i++)
            {
                temp = m_hmacsha1.ComputeHash(temp);
                for (int j = 0; j < BlockSize; j++)
                {
                    ret[j] ^= temp[j];
                }
            }

            // increment the block count.
            m_block++;
            return(ret);
        }
Beispiel #16
0
        private int ReadTransformOneBlock(byte[] buffer, int offset, int last)
        {
            if (isFinalBlock)
            {
                throw new InvalidOperationException();
            }

            int bytesRemaining = last - offset;
            int bytesToRead    = (bytesRemaining > BLOCK_SIZE_IN_BYTES)
                                  ? BLOCK_SIZE_IN_BYTES
                                  : bytesRemaining;

            // update the counter
            Array.Copy(BitConverter.GetBytes(_nonce++), 0, counter, 0, 4);

            // Determine if this is the final block
            if ((bytesToRead == bytesRemaining) && (totalBytesLeftToRead == 0))
            {
                hmac.TransformFinalBlock(buffer, offset, bytesToRead);
                counterOut = transform.TransformFinalBlock(counter,
                                                           0,
                                                           BLOCK_SIZE_IN_BYTES);
                isFinalBlock = true;
            }
            else
            {
                hmac.TransformBlock(buffer, offset, bytesToRead, null, 0);
                transform.TransformBlock(counter,
                                         0, // offset
                                         BLOCK_SIZE_IN_BYTES,
                                         counterOut,
                                         0); // offset
            }

            XorInPlace(buffer, offset, bytesToRead);
            return(bytesToRead);
        }
Beispiel #17
0
        /// <summary>
        /// Returns the SHA1 HMAC of the given <paramref name="prefix"/>, the given <paramref name="request"/>'s
        /// body, and the given <paramref name="suffix"/> (in that order).
        /// </summary>
        /// <param name="request">The current <see cref="HttpRequest"/>.</param>
        /// <param name="secret">The key data used to initialize the <see cref="HMACSHA1"/>.</param>
        /// <param name="prefix">
        /// If non-<see langword="null"/> and non-empty, additional <c>byte</c>s to include in the hashed content
        /// before the <paramref name="request"/>'s body.
        /// </param>
        /// <param name="suffix">
        /// If non-<see langword="null"/> and non-empty, additional <c>byte</c>s to include in the hashed content
        /// after the <paramref name="request"/>'s body.
        /// </param>
        /// <returns>
        /// A <see cref="Task"/> that on completion provides a <see cref="byte"/> array containing the SHA1 HMAC of
        /// the <paramref name="prefix"/>, the <paramref name="request"/>'s body, and the <paramref name="suffix"/>
        /// (in that order).
        /// </returns>
        protected virtual async Task <byte[]> ComputeRequestBodySha1HashAsync(
            HttpRequest request,
            byte[] secret,
            byte[] prefix,
            byte[] suffix)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            if (secret == null)
            {
                throw new ArgumentNullException(nameof(secret));
            }
            if (secret.Length == 0)
            {
                throw new ArgumentException(Resources.General_ArgumentCannotBeNullOrEmpty);
            }

            await WebHookHttpRequestUtilities.PrepareRequestBody(request);

            using (var hasher = new HMACSHA1(secret))
            {
                try
                {
                    if (prefix != null && prefix.Length > 0)
                    {
                        hasher.TransformBlock(
                            prefix,
                            inputOffset: 0,
                            inputCount: prefix.Length,
                            outputBuffer: null,
                            outputOffset: 0);
                    }

                    // Split body into 4K chunks.
                    var buffer      = new byte[4096];
                    var inputStream = request.Body;
                    int bytesRead;
                    while ((bytesRead = await inputStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                    {
                        hasher.TransformBlock(
                            buffer,
                            inputOffset: 0,
                            inputCount: bytesRead,
                            outputBuffer: null,
                            outputOffset: 0);
                    }

                    if (suffix != null && suffix.Length > 0)
                    {
                        hasher.TransformBlock(
                            suffix,
                            inputOffset: 0,
                            inputCount: suffix.Length,
                            outputBuffer: null,
                            outputOffset: 0);
                    }

                    hasher.TransformFinalBlock(Array.Empty <byte>(), inputOffset: 0, inputCount: 0);

                    return(hasher.Hash);
                }
                finally
                {
                    // Reset Position because JsonInputFormatter et cetera always start from current position.
                    request.Body.Seek(0L, SeekOrigin.Begin);
                }
            }
        }
Beispiel #18
0
        private int ProcessOneBlockWriting(byte[] buffer, int offset, int last)
        {
            if (_finalBlock)
            {
                throw new Exception("The final block has already been transformed.");
            }

            int bytesRemaining = last - offset;
            int bytesToRead    = (bytesRemaining > BLOCK_SIZE_IN_BYTES)
                ? BLOCK_SIZE_IN_BYTES
                : bytesRemaining;

            // update the counter
            System.Array.Copy(BitConverter.GetBytes(_nonce++), 0, counter, 0, 4);


            if (bytesToRead == (last - offset))
            {
                // We're doing the last bytes in this batch.
                //
                // For the AES encryption stream to work properly, We must transform full
                // blocks of 16 bytes each, until the very last one.  But, we don't know
                // how to recognize the "last" bytes.  The approach taken here: buffer
                // the last full or partial block of bytes in a batch.  Then at time of
                // Close(), we set the _NextXformWillBeFinal flag and flush that buffer.
                //
                // This works when the caller writes in odd-sized batches, for example
                // 5000 bytes, or in batches that are neat multiples of block-size (16).


                if (_NextXformWillBeFinal)
                {
                    //Console.WriteLine("WinZipAesCipherStream::ProcessOneBlockWriting:   _NextXformWillBeFinal = true");
                    counterOut = _xform.TransformFinalBlock(counter,
                                                            0,
                                                            BLOCK_SIZE_IN_BYTES);
                    _finalBlock = true;
                }

                else if (buffer == _PendingWriteBuffer && bytesToRead == BLOCK_SIZE_IN_BYTES)
                {
//          Console.WriteLine("POBW({0},{1,5},{2,5}): pc({4})  flushing {3} bytes ...",
//                    _NextXformWillBeFinal, offset, last, bytesToRead, _pendingCount);
                }


                else
                {
                    // NOT the final block, therefore buffer it.

//          Console.WriteLine("POBW({0},{1,5},{2,5}): pc({4})  buffering {3} more bytes ...",
//                    _NextXformWillBeFinal, offset, last, bytesToRead, _pendingCount);

                    Array.Copy(buffer, offset,
                               _PendingWriteBuffer, _pendingCount,
                               bytesToRead);

                    _pendingCount += bytesToRead;

                    // remember to decrement the nonce.
                    _nonce--;
                    return(0);
                }
            }


            if (!_finalBlock)
            {
                // Next, do the AES transform.  According to the AES/CTR method used
                // by WinZip, apply the transform to the counter, and then XOR
                // the result with the ciphertext to get the plaintext.
                _xform.TransformBlock(counter,
                                      0, // offset
                                      BLOCK_SIZE_IN_BYTES,
                                      counterOut,
                                      0); // offset
            }


            // XOR (in place)
            //Console.Write("POBW({0},{1,5},{2,5}): ", _NextXformWillBeFinal, offset, last);
            for (int i = 0; i < bytesToRead; i++)
            {
                buffer[offset + i] = (byte)(counterOut[i] ^ buffer[offset + i]);
                //Console.Write("{0:X2} ", buffer[offset + i]);
            }
            //Console.WriteLine();

            // when encrypting, do the MAC last
            if (_finalBlock)
            {
                _mac.TransformFinalBlock(buffer, offset, bytesToRead);
            }
            else
            {
                _mac.TransformBlock(buffer, offset, bytesToRead, null, 0);
            }

            return(bytesToRead);
        }
Beispiel #19
0
        /// <summary>
        /// <exception cref="IOException"/>
        /// <exception cref="SpotifyAuthenticatedException"/>
        /// <exception cref="AccessViolationException"/>
        /// </summary>
        private void Connect()
        {
            #region ClientHello Setup

            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            var clientHello = new ClientHello
            {
                BuildInfo = new BuildInfo
                {
                    Platform     = Platform.Win32X86,
                    Product      = Product.Client,
                    ProductFlags = { ProductFlags.ProductFlagNone },
                    Version      = 112800721
                }
            };
            clientHello.CryptosuitesSupported.Add(Cryptosuite.Shannon);
            clientHello.LoginCryptoHello = new LoginCryptoHelloUnion
            {
                DiffieHellman = new LoginCryptoDiffieHellmanHello
                {
                    Gc = ByteString.CopyFrom(keys.PublicKeyArray()),
                    ServerKeysKnown = 1
                }
            };

            var nonce = new byte[16];
            (new Random()).NextBytes(nonce);
            clientHello.ClientNonce = ByteString.CopyFrom(nonce);
            clientHello.Padding     = ByteString.CopyFrom(new byte[1]
            {
                (byte)30
            });

            var clientHelloBytes = clientHello.ToByteArray();

            var a = conn.Result.NetworkStream;
            a.WriteByte(0x00);
            a.WriteByte(0x04);
            a.WriteByte(0x00);
            a.WriteByte(0x00);
            a.WriteByte(0x00);
            a.Flush();

            var length = 2 + 4 + clientHelloBytes.Length;
            var bytes  = BitConverter.GetBytes(length);
            a.WriteByte(bytes[0]);
            a.Write(clientHelloBytes, 0, clientHelloBytes.Length);
            a.Flush();
            var buffer = new byte[1000];
            var len    = int.Parse(a.Read(buffer, 0, buffer.Length).ToString());
            var tmp    = new byte[len];
            Array.Copy(buffer, tmp, len);

            tmp = tmp.Skip(4).ToArray();
            var accumulator = new MemoryStream();
            accumulator.WriteByte(0x00);
            accumulator.WriteByte(0x04);

            var lnarr = Utils.toByteArray(length);
            accumulator.Write(lnarr, 0, lnarr.Length);
            accumulator.Write((byte[])clientHelloBytes, 0, clientHelloBytes.Length);

            var lenArr = Utils.toByteArray(len);
            accumulator.Write(lenArr, 0, lenArr.Length);
            accumulator.Write((byte[])tmp, 0, tmp.Length);

            #endregion ClientHello Setup

            //Read APResponseMessage

            #region APResponse

            var binaryData        = accumulator.ToArray();
            var apResponseMessage = APResponseMessage.Parser.ParseFrom(tmp);
            var sharedKey         = Utils.toByteArray(keys.ComputeSharedKey(apResponseMessage
                                                                            .Challenge.LoginCryptoChallenge.DiffieHellman.Gs.ToByteArray()));

            // Check gs_signature
            var rsa        = new RSACryptoServiceProvider();
            var rsaKeyInfo = new RSAParameters
            {
                Modulus  = new BigInteger(1, serverKey).ToByteArrayUnsigned(),
                Exponent = BigInteger.ValueOf(65537).ToByteArrayUnsigned()
            };

            //Set  to the public key values.

            //Import key parameters into RSA.
            rsa.ImportParameters(rsaKeyInfo);
            var gs   = apResponseMessage.Challenge.LoginCryptoChallenge.DiffieHellman.Gs.ToByteArray();
            var sign = apResponseMessage.Challenge.LoginCryptoChallenge.DiffieHellman.GsSignature.ToByteArray();

            if (!rsa.VerifyData(gs,
                                sign,
                                HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1))
            {
                throw new AccessViolationException("Failed to verify APResponse");
            }

            // Solve challenge
            binaryData     = accumulator.ToArray();
            using var data = new MemoryStream();
            var mac = new HMACSHA1(sharedKey);
            mac.Initialize();
            for (var i = 1; i < 6; i++)
            {
                mac.TransformBlock(binaryData, 0, binaryData.Length, null, 0);
                var temp = new[] { (byte)i };
                mac.TransformBlock(temp, 0, temp.Length, null, 0);
                mac.TransformFinalBlock(new byte[0], 0, 0);
                var final = mac.Hash;
                data.Write(final, 0, final.Length);
                mac = new HMACSHA1(sharedKey);
            }

            var dataArray = data.ToArray();
            mac = new HMACSHA1(Arrays.CopyOfRange(dataArray, 0, 0x14));
            mac.TransformBlock(binaryData, 0, binaryData.Length, null, 0);
            mac.TransformFinalBlock(new byte[0], 0, 0);
            var challenge = mac.Hash;
            var clientResponsePlaintext = new ClientResponsePlaintext
            {
                LoginCryptoResponse = new LoginCryptoResponseUnion
                {
                    DiffieHellman = new LoginCryptoDiffieHellmanResponse
                    {
                        Hmac = ByteString.CopyFrom(challenge)
                    }
                },
                PowResponse    = new PoWResponseUnion(),
                CryptoResponse = new CryptoResponseUnion()
            };
            var clientResponsePlaintextBytes = clientResponsePlaintext.ToByteArray();
            len = 4 + clientResponsePlaintextBytes.Length;
            a.WriteByte(0x00);
            a.WriteByte(0x00);
            a.WriteByte(0x00);
            var bytesb = BitConverter.GetBytes(len);
            a.WriteByte(bytesb[0]);
            a.Write(clientResponsePlaintextBytes, 0, clientResponsePlaintextBytes.Length);
            a.Flush();
            try
            {
                var scrap = new byte[4];
                conn.Result.NetworkStream.ReadTimeout = 300;
                var read = conn.Result.NetworkStream.Read(scrap, 0, scrap.Length);
                if (read == scrap.Length)
                {
                    length = (scrap[0] << 24) | (scrap[1] << 16) | (scrap[2] << 8) | (scrap[3] & 0xFF);
                    var payload = new byte[length - 4];
                    conn.Result.NetworkStream.ReadComplete(payload, 0, payload.Length);
                    var failed = APResponseMessage.Parser.ParseFrom(payload)?.LoginFailed;
                    throw new SpotifyAuthenticatedException(failed);
                }
                else if (read > 0)
                {
                    throw new Exception("Read unknown data!");
                }
            }
            catch (Exception x)
            {
                // ignored
            }
            finally
            {
                conn.Result.NetworkStream.ReadTimeout = Timeout.Infinite;
            }

            using (authLock.Lock())
            {
                sendCipher = new Shannon();
                sendCipher.key(Arrays.CopyOfRange(data.ToArray(), 0x14, 0x34));

                recvCipher = new Shannon();
                recvCipher.key(Arrays.CopyOfRange(data.ToArray(), 0x34, 0x54));
                authLockEventWaitHandle.Set();
            }

            #endregion APResponse

            Debug.WriteLine("Connected successfully");
        }
Beispiel #20
0
        private int ProcessOneBlockWriting(byte[] buffer, int offset, int last)
        {
            if (_finalBlock)
            {
                throw new InvalidOperationException("The final block has already been transformed.");
            }

            int bytesRemaining = last - offset;
            int bytesToRead    = (bytesRemaining > BLOCK_SIZE_IN_BYTES)
                ? BLOCK_SIZE_IN_BYTES
                : bytesRemaining;

            // update the counter
            System.Array.Copy(BitConverter.GetBytes(_nonce++), 0, counter, 0, 4);

            // We're doing the last bytes in this batch.
            //
            // For the AES encryption stream to work properly, We must transform
            // blocks of 16 bytes, via TransformBlock, until the very last one, for
            // which we call TransformFinalBlock.  But, we don't know how to
            // recognize the "last" bytes.  The approach taken here: maintain a
            // buffer, so that one full or partial block of bytes is always
            // available.  This is the _PendingWriteBuffer.  Then at time of
            // Close(), we set the _NextXformWillBeFinal flag and flush that buffer.
            //
            // This works whether the caller writes in odd-sized batches, for example
            // 5000 bytes, or in batches that are neat multiples of the blocksize (16).


            // bytesToRead is always 16 or less.  If it is exactly what remains, then we need to
            // either, if this is the final block, do the final transform, else buffer the data.
            if (bytesToRead == (last - offset))
            {
                if (_NextXformWillBeFinal)
                {
                    //Console.WriteLine("WinZipAesCipherStream::ProcessOneBlockWriting:   _NextXformWillBeFinal = true");
                    counterOut = _xform.TransformFinalBlock(counter,
                                                            0,
                                                            BLOCK_SIZE_IN_BYTES);
                    _finalBlock = true;
                }

                else if (buffer == _PendingWriteBuffer && bytesToRead == BLOCK_SIZE_IN_BYTES)
                {
                    // this happens with a Flush(), I think.
                }

                else
                {
                    // NOT the final block, therefore buffer it.

                    Array.Copy(buffer, offset,
                               _PendingWriteBuffer, _pendingCount,
                               bytesToRead);

                    _pendingCount += bytesToRead;

                    // remember to decrement the nonce.
                    _nonce--;
                    return(bytesToRead);
                }
            }

            if (!_finalBlock)
            {
                // Next, do the AES transform.  According to the AES/CTR method used
                // by WinZip, apply the transform to the counter, and then XOR
                // the result with the ciphertext to get the plaintext.
                _xform.TransformBlock(counter,
                                      0, // offset
                                      BLOCK_SIZE_IN_BYTES,
                                      counterOut,
                                      0);  // offset
            }

            // XOR (in place)
            for (int i = 0; i < bytesToRead; i++)
            {
                buffer[offset + i] = (byte)(counterOut[i] ^ buffer[offset + i]);
            }

            // when encrypting, do the MAC last
            if (_finalBlock)
            {
                _mac.TransformFinalBlock(buffer, offset, bytesToRead);
            }
            else
            {
                _mac.TransformBlock(buffer, offset, bytesToRead, null, 0);
            }

            return(bytesToRead);
        }