public void Can_Parse_PSN_V30_Ticket()
        {
            var trueTicket = new Ps3Ticket
            {
                Header = new TicketHeader
                {
                    MajorVersion = 3,
                    MinorVersion = 0
                },
                Body = new TicketBody
                {
                    SerialId = new byte[]
                    {
                        0x02, 0xD6, 0x5A, 0x9A, 0xD8, 0x1D, 0x09, 0x34, 0x27, 0x42, 0x4B, 0x9B, 0x67, 0x29, 0x3E, 0xF2,
                        0x97, 0x55, 0xBC, 0x78
                    },
                    IssuerId   = 0x100,
                    IssuedDate = 1601425283268,
                    ExpireDate = 1601425883000,
                    UserId     = 123456,
                    Username   = "******",
                    Region     = "us",
                    Language   = 1,
                    Domain     = "b6",
                    ServiceId  = new byte[]
                    {
                        0x55, 0x50, 0x30, 0x30, 0x30, 0x36, 0x2D, 0x42, 0x4C, 0x55, 0x53, 0x33, 0x30, 0x34, 0x36, 0x34,
                        0x5F, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00
                    },
                    DateOfBirth = new DateOfBirth
                    {
                        Year  = 1981,
                        Month = 2,
                        Day   = 29
                    },
                    Age    = 39,
                    Status = 2
                },
                Footer = new TicketFooter
                {
                    CipherId  = new byte[] { 0x38, 0x2D, 0xE5, 0x8D },
                    Signature = new byte[]
                    {
                        0x30, 0x36, 0x02, 0x19, 0x00, 0xCC, 0x99, 0x5F, 0x2D, 0x33, 0x4A, 0x4C, 0x2B, 0xAD, 0xBB, 0x07,
                        0x1D, 0x21, 0xDF, 0xA1, 0x05, 0xBF, 0x12, 0xDC, 0xF1, 0x58, 0x07, 0xE8, 0x41, 0x02, 0x19, 0x00,
                        0xD3, 0xA3, 0xAA, 0xC3, 0x4A, 0x20, 0x23, 0xD9, 0x04, 0x2A, 0x7B, 0xF2, 0xE3, 0x5A, 0xDE, 0x2F,
                        0xE5, 0xB5, 0x41, 0xBA, 0x48, 0x13, 0x37, 0x41
                    }
                }
            };

            var ps3Ticket = new byte[]
            {
                0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, //header
                0x30, 0x00, 0x00, 0xA4,                         //body section
                0x00, 0x08, 0x00, 0x14,                         //service_id
                0x02, 0xD6, 0x5A, 0x9A, 0xD8, 0x1D, 0x09, 0x34, 0x27, 0x42, 0x4B, 0x9B, 0x67, 0x29, 0x3E, 0xF2, 0x97,
                0x55, 0xBC, 0x78,
                0x00, 0x01, 0x00, 0x04, //issuer_id
                0x00, 0x00, 0x01, 0x00,
                0x00, 0x07, 0x00, 0x08, //issue_date
                0x00, 0x00, 0x01, 0x74, 0xDC, 0x62, 0x98, 0xC4,
                0x00, 0x07, 0x00, 0x08, //expire_date
                0x00, 0x00, 0x01, 0x74, 0xDC, 0x6B, 0xBF, 0x78,
                0x00, 0x02, 0x00, 0x08, //user_id
                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE2, 0x40,
                0x00, 0x04, 0x00, 0x20, //username
                0x74, 0x65, 0x73, 0x74, 0x75, 0x73, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x08, 0x00, 0x04, //region/lang
                0x75, 0x73, 0x00, 0x01,
                0x00, 0x04, 0x00, 0x04, //domain
                0x62, 0x36, 0x00, 0x00,
                0x00, 0x08, 0x00, 0x18, //service_id
                0x55, 0x50, 0x30, 0x30, 0x30, 0x36, 0x2D, 0x42, 0x4C, 0x55, 0x53, 0x33, 0x30, 0x34, 0x36, 0x34, 0x5F,
                0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x30, 0x11, 0x00, 0x04, //date_of_birth
                0x07, 0xBD, 0x02, 0x1D,
                0x00, 0x01, 0x00, 0x04, //age/status
                0x27, 0x00, 0x02, 0x00,
                0x30, 0x10, 0x00, 0x00, //unknown
                0x00, 0x00, 0x00, 0x00,
                0x30, 0x02, 0x00, 0x44, //footer section
                0x00, 0x08, 0x00, 0x04, //cipher_id
                0x38, 0x2D, 0xE5, 0x8D,
                0x00, 0x08, 0x00, 0x38, //signature
                0x30, 0x36, 0x02, 0x19, 0x00, 0xCC, 0x99, 0x5F, 0x2D, 0x33, 0x4A, 0x4C, 0x2B, 0xAD, 0xBB, 0x07,
                0x1D, 0x21, 0xDF, 0xA1, 0x05, 0xBF, 0x12, 0xDC, 0xF1, 0x58, 0x07, 0xE8, 0x41, 0x02, 0x19, 0x00,
                0xD3, 0xA3, 0xAA, 0xC3, 0x4A, 0x20, 0x23, 0xD9, 0x04, 0x2A, 0x7B, 0xF2, 0xE3, 0x5A, 0xDE, 0x2F,
                0xE5, 0xB5, 0x41, 0xBA, 0x48, 0x13, 0x37, 0x41
            };


            //Act
            var ticketDecoder = new Ps3TicketDecoder();
            var decodedTicket = ticketDecoder.DecodeTicket(ps3Ticket);


            //Assert
            decodedTicket.Should().BeEquivalentTo(trueTicket);
        }
        public void Can_Parse_Rpcn_Ticket()
        {
            var trueTicket = new Ps3Ticket
            {
                Header = new TicketHeader
                {
                    MajorVersion = 2,
                    MinorVersion = 1
                },
                Body = new TicketBody
                {
                    SerialId = new byte[]
                    {
                        0x33, 0x32, 0x31, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00
                    },
                    IssuerId   = 0x33333333,
                    IssuedDate = 1601434300267,
                    ExpireDate = 1601435200267,
                    UserId     = 123456,
                    Username   = "******",
                    Region     = "br",
                    Language   = 0,
                    Domain     = "un",
                    ServiceId  = new byte[]
                    {
                        0x55, 0x50, 0x30, 0x30, 0x30, 0x36, 0x2D, 0x42, 0x4C, 0x55, 0x53, 0x33, 0x30, 0x34, 0x36, 0x34,
                        0x5F, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00
                    },
                    Status      = 0,
                    DateOfBirth = null,
                    Age         = 0
                },
                Footer = new TicketFooter
                {
                    CipherId  = new byte[] { 0x00, 0x00, 0x00, 0x00 },
                    Signature = new byte[]
                    {
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
                    }
                }
            };

            var ps3Ticket = new byte[]
            {
                0x21, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, //header
                0x30, 0x00, 0x00, 0xA4,                         //body section
                0x00, 0x08, 0x00, 0x14,                         //service_id
                0x33, 0x32, 0x31, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x04, //issuer_id
                0x33, 0x33, 0x33, 0x33,
                0x00, 0x07, 0x00, 0x08, //issue_date
                0x00, 0x00, 0x01, 0x74, 0xDC, 0xEC, 0x2F, 0x6B,
                0x00, 0x07, 0x00, 0x08, //expire_date
                0x00, 0x00, 0x01, 0x74, 0xDC, 0xF9, 0xEB, 0x0B,
                0x00, 0x02, 0x00, 0x08, //user_id
                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE2, 0x40,
                0x00, 0x04, 0x00, 0x20, //username
                0x74, 0x65, 0x73, 0x74, 0x75, 0x73, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x08, 0x00, 0x04, //region/lang
                0x62, 0x72, 0x00, 0x00,
                0x00, 0x04, 0x00, 0x04, //domain
                0x75, 0x6E, 0x00, 0x00,
                0x00, 0x08, 0x00, 0x18, //service_id
                0x55, 0x50, 0x30, 0x30, 0x30, 0x36, 0x2D, 0x42, 0x4C, 0x55, 0x53, 0x33, 0x30, 0x34, 0x36, 0x34, 0x5F,
                0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x04, //age/status
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, //status_duration?
                0x00, 0x00, 0x00, 0x00, //date_of_birth
                0x30, 0x02, 0x00, 0x44, //footer section
                0x00, 0x08, 0x00, 0x04, //cipher_id
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x08, 0x00, 0x38, //signature
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00
            };


            //Act
            var ticketDecoder = new Ps3TicketDecoder();
            var decodedTicket = ticketDecoder.DecodeTicket(ps3Ticket);


            //Assert
            decodedTicket.Should().BeEquivalentTo(trueTicket);
        }