我试过了
阿库
主要的问题是文档中只显示了“证书”,但我必须创建一个受密码保护的PFX才能正常工作。两个有用的链接是:
-
MSDN:
Digital Signing Framework of the Open Packaging Conventions
-
Creating self-signed PFX's
如第二个链接所示,您有两个用于创建PFX的选项。您可以创建一个.cer,安装它,然后使用GUI导出它,也可以下载
pvkimport
来自微软。
以下是我使用的命令(编辑:您可以使用OpenSSL来执行此操作-请参见底部):
makecert -r -n "CN=Paul Stovell" -b 01/01/2000 -e 01/01/2099 -eku 1.3.6.1.5.5.7.3.3 -sv PaulStovell.pvk PaulStovell.cer
cert2spc PaulStovell.cer PaulStovell.spc
pvkimprt -pfx PaulStovell.spc PaulStovell.pvk
这将为您留下一个受密码保护的自签名PFX文件,您可以使用该文件对文档和包进行签名。
下面是一些代码,用于创建、签名和保存包,然后重新打开并验证它。
private const string _digitalSignatureUri = "/package/services/digital-signature/_rels/origin.psdsor.rels";
static void Main(string[] args)
{
var certificate = new X509Certificate2(@"T:\Sample\Input\PaulStovell.pfx", "password");
using (var package = Package.Open("T:\\Sample\\MyPackage.zip", FileMode.Create, FileAccess.ReadWrite, FileShare.None))
{
CreatePart(package, @"/Files/File2.dll", @"T:\Sample\Input\File2.dll");
CreatePart(package, @"/Files/File2.pdb", @"T:\Sample\Input\File2.pdb");
CreatePart(package, @"/Files/File2.xml", @"T:\Sample\Input\File2.xml");
package.PackageProperties.Creator = "Paul Stovell";
package.PackageProperties.Title = "Paul Stovell's Package";
package.PackageProperties.Description = "My First Package";
package.PackageProperties.Identifier = "MyPackage";
package.PackageProperties.Version = "1.0.0.0";
// Sign the package
var toSign = package.GetParts().Select(part => part.Uri).ToList();
var uriPartSignatureOriginRelationship = PackUriHelper.CreatePartUri(new Uri(_digitalSignatureUri, UriKind.Relative));
toSign.Add(uriPartSignatureOriginRelationship);
var dsm = new PackageDigitalSignatureManager(package);
dsm.CertificateOption = CertificateEmbeddingOption.InSignaturePart;
dsm.Sign(toSign, certificate);
package.Close();
}
Console.WriteLine("Package written");
Console.WriteLine("Reading package");
using (var package = Package.Open("T:\\Sample\\MyPackage.zip", FileMode.Open, FileAccess.Read, FileShare.Read))
{
Console.WriteLine(" Package name: {0}", package.PackageProperties.Title);
var dsm = new PackageDigitalSignatureManager(package);
if (dsm.IsSigned)
{
var verificationResult = dsm.VerifySignatures(false);
var signature = dsm.Signatures[0];
Console.WriteLine(" Signed by: {0}", signature.Signer.Subject);
Console.WriteLine(" Issued by: {0}", signature.Signer.Issuer);
Console.WriteLine(" Verification: {0}", verificationResult);
}
else
{
Console.WriteLine(" Not signed.");
}
}
Console.ReadKey();
}
private static void CreatePart(Package package, string relativePath, string file)
{
var packagePartUri = new Uri(relativePath, UriKind.Relative);
var packagePart = package.CreatePart(packagePartUri, "part/" + Path.GetExtension(file));
using (var fileContent = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
CopyStream(fileContent, packagePart.GetStream());
}
}
private static void CopyStream(Stream source, Stream target)
{
// It is .NET 3.5, surely this kind of thing has gotten easier by now?
var bufferSize = 0x1000;
var buf = new byte[bufferSize];
int bytesRead = 0;
while ((bytesRead = source.Read(buf, 0, bufferSize)) > 0)
{
target.Write(buf, 0, bytesRead);
}
}
在我的机器上,输出为:
Package written
Reading package
Package name: Paul Stovell's Package
Signed by: CN=Paul Stovell
Issued by: CN=Paul Stovell
Verification: Success
我将.exe、示例文件和.pfx复制到一台新机器上,得到了完全相同的输出,这似乎表明“验证”只检查签名作者,而不询问任何认证机构。我没有在测试机器上安装任何证书,它在自己的域上运行。
编辑
:上面的代码仅验证文档本身,而不使用根CA权限验证证书。为此,请使用以下命令:
错误的
var verified = ((X509Certificate2) dsm.Signatures[0].Signer).Verify();
然后双击用于创建.pfx的.cer,并将其安装到默认位置,使其成为受信任的证书颁发机构。完成后,上述调用将返回
符合事实的
:一个有用的注释。要查看和使用计算机上的证书,请执行以下操作:
-
启动->运行并键入“mmc”
-
-
-
选择一个帐户
-
点击OK
在我的例子中,当我双击上面的.cer安装它时,它被放在
当前用户
可信根证书颁发机构
文件夹然后,您可以将其删除以撤消更改。
if (dsm.IsSigned)
{
var verificationResult = dsm.VerifySignatures(false);
var signature = dsm.Signatures[0];
var trusted = ((X509Certificate2)dsm.Signatures[0].Signer).Verify();
Console.WriteLine(" Signed by: {0}", signature.Signer.Subject);
Console.WriteLine(" Issued by: {0}", signature.Signer.Issuer);
Console.WriteLine(" Verified: {0}", verificationResult == VerifyResult.Success);
Console.WriteLine(" Trusted: {0}", trusted);
}
else
{
Console.WriteLine(" Not signed.");
}
它总是经过验证(除非我篡改了内容),但只有当证书在存储中时才可信。
例如我多读了一点书。PFX文件实际上是
PKCS 12
OpenSSL
哪个有二进制文件
available for Windows
.
安装OpenSSL后,创建一个公钥/私钥对文件。我发现我必须以管理员的身份运行下面的第二个命令,所以以管理员的身份启动这个命令可能会有好处。
openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout PaulStovell.pem -out PaulStovell.cer
它将询问关于您和您的组织创建证书的另外7个问题。接下来,创建PKCS 12。它将要求您输入密码:
openssl pkcs12 -export -out PaulStovell.pfx -in PaulStovell.pem -name "Paul Stovell"
在出现提示时输入并重新输入密码。
此时,System.IO.Packaging可以使用您的PFX并验证包签名,但它不会信任证书。要创建.cer证书,以便将其安装到受信任的证书颁发机构存储中,请执行以下操作:
openssl x509 -in PaulStovell.pem -out PaulStovell.cer