So sollten Sie keine öffentlichen/privaten Schlüssel für einen Product Key verwenden.
bessere Umsetzung
Sie ein XML-Dokument erstellen können die Funktionen beschreiben, die aktiviert sind. Oder einfach etwas Einfaches mit dem Namen und dem Datum des Kunden.
Sie verwenden den privaten Schlüssel, um das XML-Dokument zu signieren und den Hash und die Signatur mit dem Dokument zu speichern. Sie können dann das XML-Dokument in Ihrem Produkt mit dem zuvor generierten öffentlichen Schlüssel überprüfen.
Ergebnis das Dokument der Unterzeichnung:
<license>
<name>Acme Co.</name>
<expiration>20120304</expiration>
<signature>
<hash>1230u4woeifhljksdkvh23p9</hash>
<value>sdvrrvLJbmyscoVMg2pZZAtZJbBHsZFUCwE4Udv+u3TfiAms2HpLgN3cL
NtRlxyQpvWt1FKAB/SCk1jr0IasdfeDOOHhTUTyiv2vMJgCRecC1PLcrmR9ABhqk
itsjzrCt7V3eF5SpObdUFqcj+n9gasdfdQtlQeWcvKEcg=</value>
</signature>
</license>
Wenn der Benutzer den Inhalt der Lizenzdatei ändert, dann wird die Signatur nicht mehr übereinstimmen. Sie können das Dokument auch nicht erneut signieren, da sie keinen Zugriff auf Ihren privaten Schlüssel haben. Das ist wichtig, Sie liefern den PUBLIC-Schlüssel mit Ihrem Produkt, nicht den privaten Schlüssel.
Short Key Umsetzung
- Wählen Sie ein Produktcode (einige zufällige Zeichenfolge Ihr Produkt basiert auf dem Benutzernamen
- In ein bekanntes Salz zu dem Produktcode
- erstellen einen Verschlüsselungsschlüssel zu identifizieren Überprüfen, um sicherzustellen, dass es gültig ist
- Verschlüsseln Sie den salt + Produktcode mit dem neuen Schlüssel
- Erstellen Sie einen lesbaren Schlüssel aus dem verschlüsseln ted Ergebnisse.
Es wird aussehen wie 1234-1234-1234-1234
C# Lösung:
/// <summary>
/// Provides the ability to generate and validate license keys based
/// on a product code.
/// </summary>
public class LicenseKeyManager
{
/// <summary>
/// Construct a new LicenseKeyManager
/// </summary>
public LicenseKeyManager()
{
crypto = new DESCryptoServiceProvider();
}
/// <summary>
/// Set or get the product code. Once the product code
/// is manually set it will no longer be automatically
/// generated for this instance. Suggested to not
/// set the product code unless generating keys.
///
/// In this instance the ProductCode is a string
/// that identifies the machine that the license needs
/// to be generated on. This prevents the distribution
/// of keys among friends.
/// </summary>
public String ProductCode
{
set
{
productCode = value;
}
get
{
if (productCode == null)
productCode = Ethernet.MacAddress.Replace (":", "");
return productCode;
}
}
/// <summary>
/// A salt that can be added to the product code to ensure that
/// different keys are generated for different products or
/// companies.
/// Once set the salt cannot be retrieved from this object.
/// </summary>
public String Salt
{
set
{
salt = value;
}
}
/// <summary>
/// Validate a license key
/// </summary>
/// <param name="name">Name associated with the license key</param>
/// <param name="key">The license key</param>
/// <returns>True if the license key is valid</returns>
public bool IsValidKey (String name, String key)
{
if (name == null || key == null) return false;
String license = CreateLicense (name);
return license.CompareTo (key) == 0;
}
/// <summary>
/// Create a new license key associated with the given name. The key
/// will be the same if this method is reinvoked with the same name and
/// product code.
/// </summary>
/// <param name="name">Name to associate with the license key</param>
/// <returns>New License Key</returns>
public String CreateLicense (String name)
{
String licenseSource = ProductCode;
if (salt != null)
licenseSource = salt + licenseSource;
byte[] license = Encrypt(licenseSource, name);
if (license.Length > 16)
{
byte[] tmp = new byte[16];
Array.Copy (license, tmp, 16);
license = tmp;
}
else if (license.Length < 16)
{
byte[] tmp =
new byte[] {
36, 36, 36, 36, 36, 36, 36, 36,
36, 36, 36, 36, 36, 36, 36, 36};
Array.Copy (license, tmp, license.Length);
license = tmp;
}
StringBuilder sb =
new StringBuilder();
String base64License =
Convert.ToBase64String (license).ToUpper();
base64License = base64License.Replace ('+', 'F');
base64License = base64License.Replace ('/', 'A');
// Format the license key in a human readable format.
// We dont need all of the license key just enough
// so that it isn't predictable. This key won't be
// used in decrypting the license, only in comparision
// similar to that when hasing passwords.
sb.AppendFormat (
"{0}{1}{2}{3}-{4}{5}{6}{7}-" +
"{8}{9}{10}{11}-{12}{13}{14}{15}",
base64License[0], base64License[1],
base64License[2], base64License[3],
base64License[4], base64License[5],
base64License[6], base64License[7],
base64License[8], base64License[9],
base64License[10],base64License[11],
base64License[12],base64License[13],
base64License[14],base64License[15]);
return sb.ToString();
}
private byte[] GetLegalKey(string Key)
{
string sTemp = Key;
crypto.GenerateKey();
byte[] bytTemp = crypto.Key;
int KeyLength = bytTemp.Length;
if (sTemp.Length > KeyLength)
sTemp = sTemp.Substring(0, KeyLength);
else if (sTemp.Length < KeyLength)
sTemp = sTemp.PadRight(KeyLength, ' ');
return ASCIIEncoding.ASCII.GetBytes(sTemp);
}
private byte[] Encrypt(string Source, string Key)
{
// use UTF8 unicode conversion for two byte characters
byte[] byteIn = UTF8Encoding.UTF8.GetBytes(Source);
// set the private key
crypto.Key = GetLegalKey(Key);
crypto.IV = iv;
// create an Encryptor from the Provider Service instance
ICryptoTransform encryptor = crypto.CreateEncryptor();
// convert into Base64 so that the result can be used in xml
return encryptor.TransformFinalBlock (
byteIn, 0, byteIn.Length);
}
private static byte[] iv = new byte[] {63,63,63,63,63,63,63,63};
private String productCode;
private String salt;
private SymmetricAlgorithm crypto;
}
i einen kurzen Produktschlüssel benötigt – Naderi