public LicenseBlob TryDeserialize(string license, string licenseSource, bool locallySourced) { LicenseBlob blob; try { blob = LicenseBlob.Deserialize(license); } catch (Exception ex) { AcceptIssue(new Issue("Failed to parse license (from " + licenseSource + "):", LicenseBlob.TryRedact(license) + "\n" + ex, IssueSeverity.Error)); return(null); } if (!blob.VerifySignature(TrustedKeys, null)) { sink.AcceptIssue(new Issue( "License " + blob.Fields.Id + " (from " + licenseSource + ") has been corrupted or has not been signed with a matching private key.", IssueSeverity.Error)); return(null); } if (locallySourced && blob.Fields.MustBeFetched()) { sink.AcceptIssue(new Issue( "This license cannot be installed directly; it must be fetched from a license server", LicenseBlob.TryRedact(license), IssueSeverity.Error)); return(null); } return(blob); }
static bool Validate(string licenseStr, BigInteger mod, BigInteger exp, StringBuilder log) { var blob = LicenseBlob.Deserialize(licenseStr); log?.AppendLine("---------------------------------------------"); log?.AppendLine("Parsed info: " + blob.Fields); log?.AppendLine("Plaintext hash: " + BitConverter .ToString(new SHA512Managed().ComputeHash(blob.Data)) .ToLower() .Replace("-", "")); return(blob.VerifySignature(new[] { new RSADecryptPublic(mod, exp) }, log)); }
/// <summary> /// We have a layer of caching by string. This does not need to be fast. /// </summary> /// <param name="b"></param> public void Add(LicenseBlob b) { // Prevent duplicate signatures if (dict.TryAdd(BitConverter.ToString(b.Signature), b)) { //New/unique - ensure fetcher is created if (b.Fields.IsRemotePlaceholder()) { Secret = b.Fields.GetSecret(); IsRemote = true; TryUpdateLicenseServersInfo(b); RecreateFetcher(); } LocalLicenseChange(); } }
public static LicenseBlob Deserialize(string license) { var parts = license.Split(':').Select(s => s.Trim()).ToList(); if (parts.Count < 2) { throw new ArgumentException( "Not enough ':' delimited segments in license key; failed to deserialize: \"" + license + "\"", nameof(license)); } var dataBytes = Convert.FromBase64String(parts[parts.Count - 2]); var b = new LicenseBlob { Original = license, Signature = Convert.FromBase64String(parts[parts.Count - 1]), Data = dataBytes, Fields = new LicenseDetails(System.Text.Encoding.UTF8.GetString(dataBytes)) }; // b.Info = System.Text.Encoding.UTF8.GetString(b.Data); // b.Comments = parts.Take(parts.Count - 2); return(b); }
public static bool Revalidate(this ILicenseBlob b, IEnumerable <RSADecryptPublic> trustedKeys) { var ourCopy = LicenseBlob.Deserialize(b.Original); return(ourCopy.VerifySignature(trustedKeys, null) && ourCopy.Fields.DataMatches(b.Fields)); }
void OnFetchResult(string body, IReadOnlyCollection <LicenseFetcher.FetchResult> results) { if (body != null) { Last200 = parent.Clock.GetUtcNow(); var license = parent.TryDeserialize(body, "remote server", false); if (license != null) { var newId = license.Fields.Id; if (newId == Id) { remoteLicense = license; // Victory! (we're ignoring failed writes/duplicates) parent.Cache.TryPut(fetcher.CacheKey, body); LastSuccess = parent.Clock.GetUtcNow(); lastWorkingUri = results.Last().FullUrl; } else { parent.AcceptIssue(new Issue( "Remote license file does not match. Please contact [email protected]", "Local: " + Id + " Remote: " + newId, IssueSeverity.Error)); } } // TODO: consider logging a failed deserialization remotely } else { var licenseName = Id; if (results.All(r => r.HttpCode == 404 || r.HttpCode == 403)) { parent.AcceptIssue(new Issue("No such license (404/403): " + licenseName, string.Join("\n", results.Select(r => "HTTP 404/403 fetching " + RedactSecret(r.ShortUrl))), IssueSeverity.Error)); // No such subscription key.. but don't downgrade it if exists. var cachedString = parent.Cache.Get(fetcher.CacheKey); int temp; if (cachedString == null || !int.TryParse(cachedString, out temp)) { parent.Cache.TryPut(fetcher.CacheKey, results.First().HttpCode.ToString()); } Last404 = parent.Clock.GetUtcNow(); } else if (results.All(r => r.LikelyNetworkFailure)) { // Network failure. Make sure the server can access the remote server parent.AcceptIssue(fetcher.FirewallIssue(licenseName, results.FirstOrDefault())); LastTimeout = parent.Clock.GetUtcNow(); } else { parent.AcceptIssue(new Issue("Exception(s) occurred fetching license " + licenseName, RedactSecret(string.Join("\n", results.Select(r => $"{r.HttpCode} {r.FullUrl} LikelyTimeout: {r.LikelyNetworkFailure} Error: {r.FetchError?.ToString()}"))), IssueSeverity.Error)); LastException = parent.Clock.GetUtcNow(); } } LocalLicenseChange(); }