public static R <Licenses, string> Parse(ReadOnlySpan <byte> data) { if (data.Length < 1) { return("License too short"); } var version = data[0]; if (version != 1) { return("Unsupported version"); } // Read licenses var res = new Licenses(); data = data.Slice(1); while (data.Length > 0) { // Read next license var result = LicenseBlock.Parse(data); if (!result.Ok) { return(result.Error); } var(license, len) = result.Value; // TODO Check valid times res.Blocks.Add(license); data = data.Slice(len); } return(res); }
#pragma warning restore CS8618 public static R <(LicenseBlock block, int read), string> Parse(ReadOnlySpan <byte> data) { if (data.Length < MinBlockLen) { return("License too short"); } if (data[0] != 0) { return($"Wrong key kind {data[0]} in license"); } LicenseBlock block; int read; switch (data[33]) { case 0: var result = ReadNullString(data.Slice(46)); if (!result.Ok) { return(result.Error); } var nullStr = result.Value; block = new IntermediateLicenseBlock(nullStr.str); read = 5 + nullStr.read; break; case 2: if (!Enum.IsDefined(typeof(ServerLicenseType), data[42])) { return($"Unknown license type {data[42]}"); } result = ReadNullString(data.Slice(47)); if (!result.Ok) { return(result.Error); } nullStr = result.Value; block = new ServerLicenseBlock(result.Value.str, (ServerLicenseType)data[42]); read = 6 + nullStr.read; break; case 32: block = new EphemeralLicenseBlock(); read = 0; break; default: return($"Invalid license block type {data[33]}"); } block.NotValidBefore = Tools.UnixTimeStart.AddSeconds(BinaryPrimitives.ReadUInt32BigEndian(data.Slice(34)) + 0x50e22700uL); block.NotValidAfter = Tools.UnixTimeStart.AddSeconds(BinaryPrimitives.ReadUInt32BigEndian(data.Slice(38)) + 0x50e22700uL); if (block.NotValidAfter < block.NotValidBefore) { return("License times are invalid"); } block.Key = data.Slice(1, 32).ToArray(); var allLen = MinBlockLen + read; var hash = TsCrypt.Hash512It(data[1..allLen].ToArray());