单机软件的一个特点是,你毫无保留地把程序都交给用户了。所以,如果软件能够反编译,任何的证书都形同虚设。也正因为此,我们下面所谈的,都是在软件已经过保护,不能反编译为前提的。
软件的认证,一般有三种元素存在:
-
机器认证:只能在特定的机器上运行。 -
用户认证:认证跟特定的用户名关联。 -
时间认证:有固定的有效期,超出时间认证失效。
对于单机软件来说,更多时候是机器认证和时间认证结合,用户认证不太可用,因为用户名可以交给其他人使用。本文先介绍机器认证的方法。
软件证书制作和使用的流程如下图所示:
我们先来看软件证书制作,其步骤为:
-
客户软件生成一个机器码,并把机器码交给软件拥有者。 -
软件拥有者把机器码跟软件有效期结合在一起,形成软件认证信息的明文。 -
使用非对称密钥中的私钥,对明文信息进行签名。 -
明文信息和签名结合在一起,即形成软件证书。
而软件证书的使用,也就是验证过程,是跟制作过程基本反过来的:
-
客户软件得到证书之后,先分解出明文信息和签名。 -
使用非对称密钥中的公钥,对明文信息进行验证。 -
客户软件再次生成机器码,跟明文信息中的机器码进行匹配。 -
客户软件根据当前时间,跟明文信息中的有效期进行比较。
?
下面解释一下上面所提的数字签名相关的内容。
软件证书里包含机器码和有效期等信息,如果它是以一种明文方式呈现,那用户很容易就能将其修改。所以我们需要对信息进行加密。
我们可以使用一种对称加密的方法,也就是用一个密码加密,用同样的密码解密。我们上面提到过,单机软件就是把整个程序都交给用户了。无论密码藏在哪里,最终是有办法找到的。一旦找到了这个密码,所有软件证书的破解将迎刃而解。所以这种方法是行不通的。
而另外一种方法是,我没办法把密码藏起来,那就直接把密码告诉你好了;我没办法防止你改软件证书,那你随便改好了。关键就在于,证书一旦被修改,软件就能发现。这里使用的是非对称加密的数字签名方法。在非对称加密里,顾名思义,私钥是不能公开的,公钥是能够公开的。它们有两种使用方法:
1. 公钥加密,私钥解密。
2. 私钥加密,公钥验证。
我们这里使用的是第2种方法。下面是C#里使用RSA进行签名和验证的示例代码:
byte[] Sign(byte[] content, string privateKey)
{
var sha256 = new SHA256CryptoServiceProvider();
byte[] hash = sha256.ComputeHash(content);
RSACryptoServiceProvider key = new RSACryptoServiceProvider();
key.FromXmlString(privateKey);
RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key);
formatter.SetHashAlgorithm("SHA256");
return formatter.CreateSignature(hash);
}
bool CheckSign(byte[] content, string publicKey, byte[] signData)
{
try
{
var sha256 = new SHA256CryptoServiceProvider();
byte[] hash = sha256.ComputeHash(content);
RSACryptoServiceProvider key = new RSACryptoServiceProvider();
key.FromXmlString(publicKey);
RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key);
deformatter.SetHashAlgorithm("SHA256");
if (deformatter.VerifySignature(hash, signData))
{
return true;
}
return false;
}
catch
{
return false;
}
}
|