/// <summary> /// This method will access the license keys that belong to the user by asking them to /// login into their account and authorize this application to get a token that will /// return them. In rare cases, we may get a successful authorization but not successful /// retrieval of license keys. In this case, the value tuple that is returned by this /// method will contain a token (Item3/licenseKeyToken). Next time you try to repeat /// the attempt, pass in the returned token into "existingToken" parameter. /// </summary> /// <param name="machineCode">The machine code you want to authorize.</param> /// <param name="token">The token to access the "GetToken" method.</param> /// <param name="appName">A user friendly name of your application.</param> /// <param name="tokenExpires">Sets the number of days the token should be valid.</param> /// <param name="RSAPublicKey">The RSA public key can be found here: /// https://app.cryptolens.io/User/Security </param> /// <param name="existingToken">If you have already called this method once /// and received a token as a result (despite an error), you can enter it here /// to avoid duplicate authorization by the user.</param> public static GetLicenseKeysResult GetLicenseKeys(string machineCode, string token, string appName, int tokenExpires, string RSAPublicKey, string existingToken = null) { string tokenNew = existingToken; if (string.IsNullOrEmpty(existingToken)) { var auth = AuthMethods.CreateAuthRequest(new Scope { GetLicenseKeys = true }, appName, machineCode, AuthMethods.GetTokenId(token), tokenExpires); for (int i = 0; i < 100; i++) { try { tokenNew = AuthMethods.GetToken(auth, token); } catch (Exception ex) { } if (tokenNew != null) { break; } Thread.Sleep(3000); } if (tokenNew == null) { return(new GetLicenseKeysResult { Error = "Timeout reached. The user took too long time to authorize this request." }); } } GetLicenseKeysResultLinqSign result = null; try { result = HelperMethods.SendRequestToWebAPI3 <GetLicenseKeysResultLinqSign>(new GetLicenseKeysModel { Sign = true, MachineCode = machineCode }, "/User/GetLicenseKeys", tokenNew); } catch (Exception ex) { return(new GetLicenseKeysResult { LicenseKeyToken = tokenNew, Error = "Could not contact SKM: " + ex.InnerException }); } if (result == null || result.Result == ResultType.Error) { return(new GetLicenseKeysResult { LicenseKeyToken = tokenNew, Error = "An error occurred in the method: " + result?.Message }); } var licenseKeys = Convert.FromBase64String(result.Results); var activatedMachines = Convert.FromBase64String(result.ActivatedMachineCodes); var date = BitConverter.GetBytes(result.SignDate); if (!BitConverter.IsLittleEndian) { Array.Reverse(date); } var toSign = licenseKeys.Concat(activatedMachines.Concat(date)).ToArray(); // only if sign enabled. #if NET40 || NET46 || NET35 using (var rsaVal = new RSACryptoServiceProvider()) { rsaVal.FromXmlString(RSAPublicKey); if (!rsaVal.VerifyData(toSign, "SHA256", Convert.FromBase64String(result.Signature))) { // verification failed. return(new GetLicenseKeysResult { LicenseKeyToken = tokenNew, Error = "Verification of the signature failed." }); } } #else using (var rsaVal = RSA.Create()) { rsaVal.ImportParameters(SecurityMethods.FromXMLString(RSAPublicKey)); if (!rsaVal.VerifyData(toSign, Convert.FromBase64String(result.Signature), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) { // verification failed. return(new GetLicenseKeysResult { LicenseKeyToken = tokenNew, Error = "Verification of the signature failed." }); } } #endif var machineCodes = JsonConvert.DeserializeObject <List <String> >(System.Text.UTF8Encoding.UTF8.GetString(activatedMachines)); if (machineCodes?.Count != 0 && !machineCodes.Contains(machineCode)) { return(new GetLicenseKeysResult { LicenseKeyToken = tokenNew, Error = "This machine code has not been authorized." }); } return(new GetLicenseKeysResult { Licenses = JsonConvert.DeserializeObject <List <KeyInfoResult> >(System.Text.UTF8Encoding.UTF8.GetString((licenseKeys))).Select(x => x.LicenseKey).ToList(), LicenseKeyToken = tokenNew }); }