Exemplo n.º 1
0
        public Protocol Authenticate(string username, string password)
        {
            /* Number of authentication tries. */
            int tries = 3;

            /* Set username and password. */
            this._username = Encoding.UTF8.GetBytes(username);
            this._password = Encoding.UTF8.GetBytes(password);

            while (true)
            {
                /* Connect to a spotify server. */
                this._protocol.Connect();

                /* Send and receive initial packets. */
                try
                {
                    this._protocol.SendInitialPacket();
                    this._protocol.ReceiveInitialPacket();

                    break;
                }
                catch (ProtocolException e)
                {
                    if (tries-- > 0)
                    {
                        continue;
                    }

                    throw new AuthenticationException(e);
                }
            }

            /* Generate auth hash. */
            this.GenerateAuthHash();

            /* Compute shared key (Diffie Hellman key exchange). */
            this._dhSharedKey = DH.ComputeSharedKey(this._dhClientKeyPair.PrivateKey, this._dhServerPublicKey);

            /* Prepare a message to authenticate. */
            ByteBuffer buffer = ByteBuffer.Allocate(((this._authHash.Length + this._clientRandom.Length) + this._serverRandom.Length) + 1);

            /* Append auth hash, client and server random to message. */
            buffer.Put(this._authHash);
            buffer.Put(this._clientRandom);
            buffer.Put(this._serverRandom);
            buffer.Put((byte)0x00); /* Changed later */
            buffer.Flip();

            /* Get message bytes and allocate space for HMACs. */
            byte[] bytes  = new byte[buffer.Remaining];
            byte[] hmac   = new byte[5 * 20];
            int    offset = 0;

            buffer.Get(bytes);

            /* Run HMAC SHA-1 over message. 5 times. */
            for (int i = 1; i <= 5; i++)
            {
                /* Change last byte (53) of message. */
                bytes[bytes.Length - 1] = (byte)i;

                /* Compute HMAC SHA-1 using the shared key. */
                Hash.HmacSha1(bytes, this._dhSharedKey, hmac, offset);

                /* Overwrite first 20 bytes of message with output from this round. */
                for (int j = 0; j < 20; j++)
                {
                    bytes[j] = hmac[offset + j];
                }

                /* Advance to next position. */
                offset += 20;
            }
            /* Use field of HMACs to setup keys for Shannon stream cipher (key length: 32). */
            Array.Copy(hmac, 20, this._keySend, 0, 32);
            Array.Copy(hmac, 52, this._keyRecv, 0, 32);

            /* Set stream cipher keys. */
            this._shannonSend.key(this._keySend);
            this._shannonRecv.key(this._keyRecv);

            /*
             * First 20 bytes of HMAC output is used to key another HMAC computed
             * for the second authentication packet send by the client.
             */
            Array.Copy(hmac, 0, this._keyHmac, 0, 20);

            /* Solve puzzle */
            this.SolvePuzzle();

            /* Generate HMAC */
            this.GenerateAuthHmac();
            try
            {
                this._protocol.SendAuthenticationPacket();
                this._protocol.ReceiveAuthenticationPacket();
            }
            catch (ProtocolException e)
            {
                throw new AuthenticationException(e);
            }
            return(this._protocol);
        }