<license>
<name>Acme Co.</name>
<expiration>20120304</expiration>
</license>
プライベートキーを使用してXMLドキュメントに署名し、ハッシュと署名をドキュメントに保存します。これで、前に生成した公開鍵を使用して、製品内のXML文書を検証できます。文書に署名する
結果:
<license>
<name>Acme Co.</name>
<expiration>20120304</expiration>
<signature>
<hash>1230u4woeifhljksdkvh23p9</hash>
<value>sdvrrvLJbmyscoVMg2pZZAtZJbBHsZFUCwE4Udv+u3TfiAms2HpLgN3cL
NtRlxyQpvWt1FKAB/SCk1jr0IasdfeDOOHhTUTyiv2vMJgCRecC1PLcrmR9ABhqk
itsjzrCt7V3eF5SpObdUFqcj+n9gasdfdQtlQeWcvKEcg=</value>
</signature>
</license>
ユーザーがライセンスファイルの内容を変更する場合は、署名が一致しなくなります。また、秘密鍵にアクセスできないため、文書に再署名することもできません。これは重要です。パブリックキーではなく、PUBLICキーを製品とともに発送することが重要です。
ショートキー実装
- 製品コードを選択します(お使いの製品
- を識別するためのいくつかのランダムな文字列は、商品コード
- に知られている塩を追加し、ユーザー名に基づいて暗号化キーを作成します。
- 塩+製品コードを新しい鍵で暗号化します
- encryptから人間が読める鍵を作成します結果を示す。
それは1234-1234-1234-1234
C#ソリューションのようになります。私は短いプロダクトキーが必要
/// <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;
}
を – Naderi