如果你想用 C# 替代 OpenSSL 的调用,通常是指替代 OpenSSL 提供的加密、解密、签名、验证等功能。C# 提供了自己的加密库,即 System.Security.Cryptography,你可以使用这些类来实现类似于 OpenSSL 的功能。
1、问题背景
今天在制作一个新的 Chrome 主题创建器时遇到一个问题。众所周知,Chrome 使用一种称为 CRX 的“新”文件格式来管理其插件和主题。它是一个基本的 zip 文件,但经过了一些修改: “Cr24”+ derkey + signature + zipFile 问题来了。只有两个 CRX 创建器,用 Ruby 或 Python 编写。我对这两种语言都不太了解(虽然对 Python 有过一些基本的经验,但主要用 PyS60),所以我想请你帮我将这个 python 应用程序转换成不依赖于外部程序的 C# 代码。 另外,这里有 crxmake.py 的源代码:
#!/usr/bin/python
# Cribbed from http://github.com/Constellation/crxmake/blob/master/lib/crxmake.rb
# and http://src.chromium.org/viewvc/chrome/trunk/src/chrome/tools/extensions/chromium_extension.py?revision=14872&content-type=text/plain&pathrev=14872
# from: http://grack.com/blog/2009/11/09/packing-chrome-extensions-in-python/
import sys
from array import *
from subprocess import *
import os
import tempfile
def main(argv):
arg0,dir,key,output = argv
# zip up the directory
input = dir + ".zip"
if not os.path.exists(input):
os.system("cd %(dir)s; zip -r ../%(input)s . -x '.svn/*'" % locals())
else:
print "'%s' already exists using it" % input
# Sign the zip file with the private key in PEM format
signature = Popen(["openssl", "sha1", "-sign", key, input], stdout=PIPE).stdout.read();
# Convert the PEM key to DER (and extract the public form) for inclusion in the CRX header
derkey = Popen(["openssl", "rsa", "-pubout", "-inform", "PEM", "-outform", "DER", "-in", key], stdout=PIPE).stdout.read();
out=open(output, "wb");
out.write("Cr24") # Extension file magic number
header = array("l");
header.append(2); # Version 2
header.append(len(derkey));
header.append(len(signature));
header.tofile(out);
out.write(derkey)
out.write(signature)
out.write(open(input).read())
os.unlink(input)
print "Done."
if __name__ == '__main__':
main(sys.argv)
你能帮我吗?
2、解决方案
我们可以用 C# 代码替换 openSSL 调用,并创建一个 C# 应用程序来生成 CRX 文件。 以下步骤描述了如何用 C# 代码替换 openSSL 调用,并创建一个 C# 应用程序来生成 CRX 文件:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Encodings;
namespace CRXMake
{
class Program
{
static void Main(string[] args)
{
// Get the command line arguments.
if (args.Length != 4)
{
Console.WriteLine("Usage: CRXMake directory key output");
return;
}
string directory = args[0];
string keyFile = args[1];
string outputFile = args[2];
// Create a temporary directory to store the zip file.
string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(tempDirectory);
// Zip the directory.
string zipFile = Path.Combine(tempDirectory, "extension.zip");
ZipFile.CreateFromDirectory(directory, zipFile);
// Sign the zip file.
string signatureFile = Path.Combine(tempDirectory, "signature");
SignFile(zipFile, keyFile, signatureFile);
// Convert the PEM key to DER.
string derKeyFile = Path.Combine(tempDirectory, "derkey");
ConvertPemToDer(keyFile, derKeyFile);
// Create the CRX file.
CreateCrxFile(zipFile, derKeyFile, signatureFile, outputFile);
// Delete the temporary directory.
Directory.Delete(tempDirectory, true);
Console.WriteLine("CRX file created successfully.");
}
static void SignFile(string inputFile, string keyFile, string outputFile)
{
// Read the key file.
AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)new PemReader(new FileStream(keyFile, FileMode.Open)).ReadObject();
// Sign the file.
ISigner signer = SignerUtilities.GetSigner("SHA256withRSA");
signer.Init(true, keyPair.Private);
byte[] data = File.ReadAllBytes(inputFile);
byte[] signature = signer.GenerateSignature(data);
// Write the signature to a file.
File.WriteAllBytes(outputFile, signature);
}
static void ConvertPemToDer(string inputFile, string outputFile)
{
// Read the PEM file.
AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)new PemReader(new FileStream(inputFile, FileMode.Open)).ReadObject();
// Convert the key to DER format.
RsaKeyParameters rsaKey = (RsaKeyParameters)keyPair.Private;
byte[] derKey = rsaKey.GetEncoded();
// Write the DER key to a file.
File.WriteAllBytes(outputFile, derKey);
}
static void CreateCrxFile(string zipFile, string derKeyFile, string signatureFile, string outputFile)
{
// Read the zip file.
byte[] zipData = File.ReadAllBytes(zipFile);
// Read the DER key.
byte[] derKey = File.ReadAllBytes(derKeyFile);
// Read the signature.
byte[] signature = File.ReadAllBytes(signatureFile);
// Create the CRX file header.
byte[] header = new byte[16];
Array.Copy(Encoding.ASCII.GetBytes("Cr24"), header, 4);
BitConverter.GetBytes(2).CopyTo(header, 4);
BitConverter.GetBytes(derKey.Length).CopyTo(header, 8);
BitConverter.GetBytes(signature.Length).CopyTo(header, 12);
// Create the CRX file.
byte[] crxData = new byte[header.Length + derKey.Length + signature.Length + zipData.Length];
Array.Copy(header, crxData, header.Length);
Array.Copy(derKey, 0, crxData, header.Length, derKey.Length);
Array.Copy(signature, 0, crxData, header.Length + derKey.Length, signature.Length);
Array.Copy(zipData, 0, crxData, header.Length + derKey.Length + signature.Length, zipData.Length);
// Write the CRX file.
File.WriteAllBytes(
C# 提供了强大的加密功能,通过 System.Security.Cryptography
命名空间,你可以轻松地实现 OpenSSL 中的一些常见操作,如 RSA 加密、哈希计算、HMAC、证书操作等。与 OpenSSL 的命令行工具不同,C# 的加密操作通常需要通过编程实现,但它同样强大且灵活。
如果你需要更复杂的操作(如生成自签名证书、处理 PEM 格式文件等),你可以使用第三方库,如 BouncyCastle 或 OpenSSL.NET,它们提供了更广泛的 OpenSSL 兼容功能。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。