示例#1
0
        public void EncodeTest1()
        {
            MockBitWriter io      = new MockBitWriter();
            Shannon       shannon = new Shannon(io);

            shannon.Encode(5);
            Assert.AreEqual(io.values.Count(), 8);
            Assert.AreEqual(io.values[0], false);
            Assert.AreEqual(io.values[1], false);
            Assert.AreEqual(io.values[2], false);
            Assert.AreEqual(io.values[3], false);
            Assert.AreEqual(io.values[4], false);
            Assert.AreEqual(io.values[5], true);
            Assert.AreEqual(io.values[6], false);
            Assert.AreEqual(io.values[7], true);
            io.Clear();
            shannon.Encode(5);
            Assert.AreEqual(io.values.Count(), 7);
            Assert.AreEqual(io.values[0], false);
            Assert.AreEqual(io.values[1], false);
            Assert.AreEqual(io.values[2], false);
            Assert.AreEqual(io.values[3], false);
            Assert.AreEqual(io.values[4], false);
            Assert.AreEqual(io.values[5], false);
            Assert.AreEqual(io.values[6], false);
        }
示例#2
0
        public void FindValueTest()
        {
            Shannon shannon = new Shannon(new MockBitWriter());

            for (int i = 0; i < 256; i++)
            {
                Assert.AreEqual(shannon.FindValue(i), i);
            }
        }
示例#3
0
        public void EncodeDecodeTest()
        {
            MockBitWriter io      = new MockBitWriter();
            Shannon       encoder = new Shannon(io);

            foreach (char character in "Lorem ipsum dolor sit amet consectetur adepiscig nullam")
            {
                encoder.Encode(character);
            }
            Shannon decoder = new Shannon(io);

            foreach (char character in "Lorem ipsum dolor sit amet consectetur adepiscig nullam")
            {
                Assert.AreEqual(decoder.Decode(), character);
            }
        }
示例#4
0
        public void DecodeTest()
        {
            MockBitWriter io      = new MockBitWriter();
            Shannon       shannon = new Shannon(io);

            io.WriteBit(false);
            io.WriteBit(false);
            io.WriteBit(false);
            io.WriteBit(false);
            io.WriteBit(false);
            io.WriteBit(true);
            io.WriteBit(false);
            io.WriteBit(true);
            Assert.AreEqual(shannon.Decode(), 5);
            io.WriteBit(false);
            io.WriteBit(false);
            io.WriteBit(false);
            io.WriteBit(false);
            io.WriteBit(false);
            io.WriteBit(false);
            io.WriteBit(false);
            Assert.AreEqual(shannon.Decode(), 5);
        }
示例#5
0
        public Session(int clientOS, int clientRevision)
        {
            /* Initialize protocol with this session. */
            this._protocol = new Protocol(this);

            /* Set client properties. */
            this._clientId       = CLIENT_ID;
            this._clientOs       = clientOS;
            this._clientRevision = clientRevision;

            /* Client and server generate 16 random bytes each. */
            this._clientRandom = new byte[16];
            this._serverRandom = new byte[16];

            RandomBytes.GetRandomBytes(ref this._clientRandom);

            /* Allocate buffer for server RSA key. */
            this._serverBlob = new byte[256];

            /* Allocate buffer for salt and auth hash. */
            this._username = null;
            this._password = null;
            this._salt     = new byte[10];
            this._authHash = new byte[20];

            /*
             * Create a private and public DH key and allocate buffer
             * for shared key. This, along with key signing, is used
             * to securely agree on a session key for the Shannon stream
             * cipher.
             */
            this._dhClientKeyPair = DH.GenerateKeyPair(768);
            this._dhSharedKey     = new byte[96];

            /* Generate RSA key pair. */
            this._rsaClientKeyPair = Sharpotify.Crypto.RSA.GenerateKeyPair(1024);

            /* Allocate buffers for HMAC and Shannon stream cipher keys. */
            this._keyHmac   = new byte[20];
            this._authHmac  = new byte[20];
            this._keyRecv   = new byte[32];
            this._keySend   = new byte[32];
            this._keyRecvIv = 0;
            this._keySendIv = 0;

            /* Stream cipher instances. */
            this._shannonRecv = new Shannon();
            this._shannonSend = new Shannon();

            /* Allocate buffer for puzzle solution. */
            this._puzzleDenominator = 0;
            this._puzzleMagic       = 0;
            this._puzzleSolution    = new byte[8];

            /* Found in Storage.dat (cache) at offset 16. Modify first byte of cache hash. */
            this._cacheHash = new byte[] {
                (byte)0xf4, (byte)0xc2, (byte)0xaa, (byte)0x05,
                (byte)0xe8, (byte)0x25, (byte)0xa7, (byte)0xb5,
                (byte)0xe4, (byte)0xe6, (byte)0x59, (byte)0x0f,
                (byte)0x3d, (byte)0xd0, (byte)0xbe, (byte)0x0a,
                (byte)0xef, (byte)0x20, (byte)0x51, (byte)0x95
            };
            this._cacheHash[0] = (byte)new Random().Next();

            /* Not initialized. */
            this._initialClientPacket = null;
            this._initialServerPacket = null;
        }
示例#6
0
        public void GetHalfIndexTest()
        {
            Shannon shannon = new Shannon(new MockBitWriter());

            Assert.AreEqual(shannon.GetHalfIndex(127, 0, 255), 127);
        }
示例#7
0
        public void GetSumOfProbabilitiesTest()
        {
            Shannon shannon = new Shannon(new MockBitWriter());

            Assert.AreEqual(shannon.GetSumOfProbabilities(), 256);
        }
示例#8
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");
        }