C# 如何使用PGP机制对文本文件进行数字签名
我有一个文本文件,我需要使用PGP方法对文本文件进行数字签名,并将签名附在文件上。请查看。它适合你的需要吗 您也可以使用Bouncy Castle,堆栈溢出的一个例子是。如下所示:C# 如何使用PGP机制对文本文件进行数字签名,c#,pgp,C#,Pgp,我有一个文本文件,我需要使用PGP方法对文本文件进行数字签名,并将签名附在文件上。请查看。它适合你的需要吗 您也可以使用Bouncy Castle,堆栈溢出的一个例子是。如下所示: using Org.BouncyCastle.Bcpg; using Org.BouncyCastle.Bcpg.OpenPgp; using Org.BouncyCastle.Security; namespace BouncyCastleTest.PGP { // http://www.progra
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Org.BouncyCastle.Security;
namespace BouncyCastleTest.PGP
{
// http://www.programcreek.com/java-api-examples/index.php?api=org.bouncycastle.bcpg.HashAlgorithmTags
// http://stackoverflow.com/questions/6337985/how-to-sign-a-txt-file-with-a-pgp-key-in-c-sharp-using-bouncy-castle-library
class SignOnly
{
public void SignFile(string hashAlgorithm, string fileName, System.IO.Stream privateKeyStream
, string privateKeyPassword, System.IO.Stream outStream)
{
PgpSecretKey pgpSec = ReadSigningSecretKey(privateKeyStream);
PgpPrivateKey pgpPrivKey = null;
pgpPrivKey = pgpSec.ExtractPrivateKey(privateKeyPassword.ToCharArray());
PgpSignatureGenerator sGen = new PgpSignatureGenerator(pgpSec.PublicKey.Algorithm, ParseHashAlgorithm(hashAlgorithm));
sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);
foreach (string userId in pgpSec.PublicKey.GetUserIds())
{
PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator();
spGen.SetSignerUserId(false, userId);
sGen.SetHashedSubpackets(spGen.Generate());
}
CompressionAlgorithmTag compression = PreferredCompression(pgpSec.PublicKey);
PgpCompressedDataGenerator cGen = new PgpCompressedDataGenerator(compression);
BcpgOutputStream bOut = new BcpgOutputStream(cGen.Open(outStream));
sGen.GenerateOnePassVersion(false).Encode(bOut);
System.IO.FileInfo file = new System.IO.FileInfo(fileName);
System.IO.FileStream fIn = new System.IO.FileStream(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
System.IO.Stream lOut = lGen.Open(bOut, PgpLiteralData.Binary, file);
int ch = 0;
while ((ch = fIn.ReadByte()) >= 0)
{
lOut.WriteByte((byte)ch);
sGen.Update((byte)ch);
}
fIn.Close();
sGen.Generate().Encode(bOut);
lGen.Close();
cGen.Close();
outStream.Close();
}
public static PgpSecretKeyRingBundle CreatePgpSecretKeyRingBundle(System.IO.Stream keyInStream)
{
return new PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(keyInStream));
}
public PgpSecretKey ReadSigningSecretKey(System.IO.Stream keyInStream)
{
PgpSecretKeyRingBundle pgpSec = CreatePgpSecretKeyRingBundle(keyInStream);
PgpSecretKey key = null;
System.Collections.IEnumerator rIt = pgpSec.GetKeyRings().GetEnumerator();
while (key == null && rIt.MoveNext())
{
PgpSecretKeyRing kRing = (PgpSecretKeyRing)rIt.Current;
System.Collections.IEnumerator kIt = kRing.GetSecretKeys().GetEnumerator();
while (key == null && kIt.MoveNext())
{
PgpSecretKey k = (PgpSecretKey)kIt.Current;
if (k.IsSigningKey)
key = k;
}
}
if (key == null)
throw new System.Exception("Wrong private key - Can't find signing key in key ring.");
else
return key;
}
public static string GetDigestName(int hashAlgorithm)
{
switch ((Org.BouncyCastle.Bcpg.HashAlgorithmTag)hashAlgorithm)
{
case Org.BouncyCastle.Bcpg.HashAlgorithmTag.Sha1:
return "SHA1";
case Org.BouncyCastle.Bcpg.HashAlgorithmTag.MD2:
return "MD2";
case Org.BouncyCastle.Bcpg.HashAlgorithmTag.MD5:
return "MD5";
case Org.BouncyCastle.Bcpg.HashAlgorithmTag.RipeMD160:
return "RIPEMD160";
case Org.BouncyCastle.Bcpg.HashAlgorithmTag.Sha256:
return "SHA256";
case Org.BouncyCastle.Bcpg.HashAlgorithmTag.Sha384:
return "SHA384";
case Org.BouncyCastle.Bcpg.HashAlgorithmTag.Sha512:
return "SHA512";
case Org.BouncyCastle.Bcpg.HashAlgorithmTag.Sha224:
return "SHA224";
case Org.BouncyCastle.Bcpg.HashAlgorithmTag.Tiger192:
return "TIGER";
default:
throw new Org.BouncyCastle.Bcpg.OpenPgp.PgpException("unknown hash algorithm tag in GetDigestName: " + hashAlgorithm);
}
}
public static Org.BouncyCastle.Bcpg.HashAlgorithmTag ParseHashAlgorithm(string hashAlgorithm)
{
switch (hashAlgorithm.ToUpper())
{
case "SHA1":
return Org.BouncyCastle.Bcpg.HashAlgorithmTag.Sha1;
case "MD2":
return Org.BouncyCastle.Bcpg.HashAlgorithmTag.MD2;
case "MD5":
return Org.BouncyCastle.Bcpg.HashAlgorithmTag.MD5;
case "RIPEMD160":
return Org.BouncyCastle.Bcpg.HashAlgorithmTag.RipeMD160;
case "SHA256":
return Org.BouncyCastle.Bcpg.HashAlgorithmTag.Sha256;
case "SHA384":
return Org.BouncyCastle.Bcpg.HashAlgorithmTag.Sha384;
case "SHA512":
return Org.BouncyCastle.Bcpg.HashAlgorithmTag.Sha512;
case "SHA224":
return Org.BouncyCastle.Bcpg.HashAlgorithmTag.Sha224;
case "TIGER":
return Org.BouncyCastle.Bcpg.HashAlgorithmTag.Tiger192;
default:
throw new Org.BouncyCastle.Bcpg.OpenPgp.PgpException("unknown hash algorithm name in ParseHashAlgorithm: " + hashAlgorithm);
}
}
public static CompressionAlgorithmTag PreferredCompression(PgpPublicKey publicKey)
{
//return CompressionAlgorithmTag.BZip2;
return CompressionAlgorithmTag.Uncompressed;
}
}
}
BouncyCastle源代码中还有很多示例:
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Bcpg.OpenPgp;
namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
{
/**
* A simple utility class that signs and verifies files.
* <p>
* To sign a file: SignedFileProcessor -s [-a] fileName secretKey passPhrase.<br/>
* If -a is specified the output file will be "ascii-armored".</p>
* <p>
* To decrypt: SignedFileProcessor -v fileName publicKeyFile.</p>
* <p>
* <b>Note</b>: this example will silently overwrite files, nor does it pay any attention to
* the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase
* will have been used.</p>
* <p>
* <b>Note</b>: the example also makes use of PGP compression. If you are having difficulty Getting it
* to interoperate with other PGP programs try removing the use of compression first.</p>
*/
public sealed class SignedFileProcessor
{
private SignedFileProcessor() {}
/**
* verify the passed in file as being correctly signed.
*/
private static void VerifyFile(
Stream inputStream,
Stream keyIn)
{
inputStream = PgpUtilities.GetDecoderStream(inputStream);
PgpObjectFactory pgpFact = new PgpObjectFactory(inputStream);
PgpCompressedData c1 = (PgpCompressedData) pgpFact.NextPgpObject();
pgpFact = new PgpObjectFactory(c1.GetDataStream());
PgpOnePassSignatureList p1 = (PgpOnePassSignatureList) pgpFact.NextPgpObject();
PgpOnePassSignature ops = p1[0];
PgpLiteralData p2 = (PgpLiteralData) pgpFact.NextPgpObject();
Stream dIn = p2.GetInputStream();
PgpPublicKeyRingBundle pgpRing = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(keyIn));
PgpPublicKey key = pgpRing.GetPublicKey(ops.KeyId);
Stream fos = File.Create(p2.FileName);
ops.InitVerify(key);
int ch;
while ((ch = dIn.ReadByte()) >= 0)
{
ops.Update((byte)ch);
fos.WriteByte((byte) ch);
}
fos.Close();
PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject();
PgpSignature firstSig = p3[0];
if (ops.Verify(firstSig))
{
Console.Out.WriteLine("signature verified.");
}
else
{
Console.Out.WriteLine("signature verification failed.");
}
}
/**
* Generate an encapsulated signed file.
*
* @param fileName
* @param keyIn
* @param outputStream
* @param pass
* @param armor
*/
private static void SignFile(
string fileName,
Stream keyIn,
Stream outputStream,
char[] pass,
bool armor,
bool compress)
{
if (armor)
{
outputStream = new ArmoredOutputStream(outputStream);
}
PgpSecretKey pgpSec = PgpExampleUtilities.ReadSecretKey(keyIn);
PgpPrivateKey pgpPrivKey = pgpSec.ExtractPrivateKey(pass);
PgpSignatureGenerator sGen = new PgpSignatureGenerator(pgpSec.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);
foreach (string userId in pgpSec.PublicKey.GetUserIds())
{
PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator();
spGen.SetSignerUserId(false, userId);
sGen.SetHashedSubpackets(spGen.Generate());
// Just the first one!
break;
}
Stream cOut = outputStream;
PgpCompressedDataGenerator cGen = null;
if (compress)
{
cGen = new PgpCompressedDataGenerator(CompressionAlgorithmTag.ZLib);
cOut = cGen.Open(cOut);
}
BcpgOutputStream bOut = new BcpgOutputStream(cOut);
sGen.GenerateOnePassVersion(false).Encode(bOut);
FileInfo file = new FileInfo(fileName);
PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
Stream lOut = lGen.Open(bOut, PgpLiteralData.Binary, file);
FileStream fIn = file.OpenRead();
int ch = 0;
while ((ch = fIn.ReadByte()) >= 0)
{
lOut.WriteByte((byte) ch);
sGen.Update((byte)ch);
}
fIn.Close();
lGen.Close();
sGen.Generate().Encode(bOut);
if (cGen != null)
{
cGen.Close();
}
if (armor)
{
outputStream.Close();
}
}
public static void Main(
string[] args)
{
// TODO provide command-line option to determine whether to use compression in SignFile
if (args[0].Equals("-s"))
{
Stream keyIn, fos;
if (args[1].Equals("-a"))
{
keyIn = File.OpenRead(args[3]);
fos = File.Create(args[2] + ".asc");
SignFile(args[2], keyIn, fos, args[4].ToCharArray(), true, true);
}
else
{
keyIn = File.OpenRead(args[2]);
fos = File.Create(args[1] + ".bpg");
SignFile(args[1], keyIn, fos, args[3].ToCharArray(), false, true);
}
keyIn.Close();
fos.Close();
}
else if (args[0].Equals("-v"))
{
using (Stream fis = File.OpenRead(args[1]),
keyIn = File.OpenRead(args[2]))
{
VerifyFile(fis, keyIn);
}
}
else
{
Console.Error.WriteLine("usage: SignedFileProcessor -v|-s [-a] file keyfile [passPhrase]");
}
}
}
}
使用系统;
使用系统集合;
使用System.IO;
使用Org.BouncyCastle.Bcpg.OpenPgp;
名称空间Org.bounchycastle.Bcpg.OpenPgp.Examples
{
/**
*对文件进行签名和验证的简单实用程序类。
*
*签署文件:SignedFileProcessor-s[-a]fileName secretKey密码短语。
*如果指定了-a,则输出文件将为“ascii铠装”
*
*要解密:SignedFileProcessor-v fileName publicKeyFile
*
*注意:此示例将以静默方式覆盖文件,也不会注意
*文件名中“_CONSOLE”的规范。它还需要一个传递短语
*将被使用
*
*注意:该示例还使用PGP压缩。如果您在获取它时遇到困难
*要与其他PGP程序进行互操作,请先尝试取消使用压缩
*/
公共密封类SignedFileProcessor
{
私有SignedFileProcessor(){}
/**
*验证传入的文件是否已正确签名。
*/
私有静态无效验证文件(
流输入流,
流键控)
{
inputStream=PgpUtilities.GetDecoderStream(inputStream);
PgpObjectFactory pgpFact=新的PgpObjectFactory(inputStream);
PgpCompressedData c1=(PgpCompressedData)pgpFact.nextpgobject();
pgpFact=新的PgpObjectFactory(c1.GetDataStream());
PgpOnePassSignatureList p1=(PgpOnePassSignatureList)pgpFact.nextPGObject();
PgpOnePassSignature ops=p1[0];
PgpLiteralData p2=(PgpLiteralData)pgpFact.nextpgobject();
Stream dIn=p2.GetInputStream();
pgppublickeringbundle pgpRing=新的pgppublickeringbundle(PgpUtilities.GetDecoderStream(keyIn));
PgpPublicKey=pgpRing.GetPublicKey(ops.KeyId);
Stream fos=File.Create(p2.FileName);
操作初始验证(密钥);
int-ch;
而((ch=dIn.ReadByte())>=0)
{
操作更新((字节)ch);
fos.WriteByte((字节)ch);
}
fos.Close();
PgpSignatureList p3=(PgpSignatureList)pgpFact.NextPgpObject();
PgpSignature firstSig=p3[0];
if(运行验证(第一信号))
{
Console.Out.WriteLine(“签名已验证”);
}
其他的
{
Console.Out.WriteLine(“签名验证失败”);
}
}
/**
*生成一个封装的签名文件。
*
*@param文件名
*@param-keyIn
*@param outputStream
*@param pass
*@param装甲
*/
私有静态无效签名文件(
字符串文件名,
流键因,
流输出流,
char[]pass,
布尔盔甲,
bool(压缩)
{
if(装甲)
{
outputStream=新ArmoreOutputStream(outputStream);
}
PgpSecretKey pgpSec=PgpExampleUtilities.ReadSecretKey(keyIn);
PgpPrivateKey pgpPrivKey=pgpSec.ExtractPrivateKey(通过);
PgpSignatureGenerator sGen=新的PgpSignatureGenerator(pgpSec.PublicKey.Algorithm,HashAlgorithmTag.Sha1);
sGen.InitSign(PgpSignature.BinaryDocument,pgpPrivKey);
foreach(pgpSec.PublicKey.GetUserIds()中的字符串userId)
{
PgpSignatureSubpacketGenerator spGen=新的PgpSignatureSubpacketGenerator();
spGen.SetSignerUserId(false,userId);
sGen.SetHashedSubpackets(spGen.Generate());
//就第一个!
打破
}
Stream cOut=outputStream;
PgpCompressedDataGenerator cGen=null;
如果(压缩)
{
cGen=新的PGP压缩数据发生器(CompressionAlgorithmTag.ZLib);
cOut=cGen.Open(cOut);
}
BcpgOutputStream bOut=新的BcpgOutputStream(cOut);
sGen.GenerateOnePassVersion(false).编码(bOut);
FileInfo file=新的FileInfo(文件名);
PgpLiteralDataGenerator lGen=新的PgpLiteralDataGenerator();
Stream lOut=lGen.Open(bOut,PgpLiteralData.Binary,file);
FileStream fIn=file.OpenRead();
int ch=0;
而((ch=fIn.ReadByte())>=0)
{
lOut.WriteByte((字节)ch);
sGen.Update((字节)ch);
}
fIn.Close();
lGen.Close();
sGen.Generate().Encode(bOut);
如果(cGen!=null)
{
cGen.Close();
}
if(装甲)
{
outputStream.Close();
}
}
公共静态真空总管(
字符串[]args)
{
//TODO提供命令行选项以确定是否在SignFile中使用压缩
如果(args[0]。等于(“-s”))
{
Stream-keyIn,fos;
if(args[1]。等于(“-a”))
{
keyIn=File.OpenRead(args[3]);
fos=File.Create(args[2]+“.asc”);
签名文件(args[2],键入,fos,args[4]。ToCha