gpt4 book ai didi

c# - PGP 加密和解密

转载 作者:可可西里 更新时间:2023-11-01 07:51:20 30 4
gpt4 key购买 nike

我真的很苦恼,我需要在 C# 中使用 BouncyCaSTLe 加密和解密字符串。我确实确实尝试过自己做这件事。我确实设法创建了自己的 key (私钥和公钥)。

请记住,我刚从大学毕业。

最佳答案

我花了一段时间才找到一个在 PGP 中使用充气城堡的好例子。这就是我在生产中使用的。我很确定它来自 here .

using System;
using System.IO;
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.IO;

namespace FileEncryptionTasks.Helpers.PGP
{
public static class PGPEncryptDecrypt
{
private const int BufferSize = 0x10000; // should always be power of 2

#region Encrypt

/*
* Encrypt the file.
*/

public static void EncryptFile(string inputFile, string outputFile, string publicKeyFile, bool armor, bool withIntegrityCheck)
{
try
{
using (Stream publicKeyStream = File.OpenRead(publicKeyFile))
{
PgpPublicKey encKey = ReadPublicKey(publicKeyStream);

using (MemoryStream bOut = new MemoryStream())
{
PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
PgpUtilities.WriteFileToLiteralData(comData.Open(bOut), PgpLiteralData.Binary, new FileInfo(inputFile));

comData.Close();
PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());

cPk.AddMethod(encKey);
byte[] bytes = bOut.ToArray();

using (Stream outputStream = File.Create(outputFile))
{
if (armor)
{
using (ArmoredOutputStream armoredStream = new ArmoredOutputStream(outputStream))
{
using (Stream cOut = cPk.Open(armoredStream, bytes.Length))
{
cOut.Write(bytes, 0, bytes.Length);
}
}
}
else
{
using (Stream cOut = cPk.Open(outputStream, bytes.Length))
{
cOut.Write(bytes, 0, bytes.Length);
}
}
}
}
}
}
catch (PgpException e)
{
throw;
}
}

#endregion Encrypt

#region Encrypt and Sign

/*
* Encrypt and sign the file pointed to by unencryptedFileInfo and
*/

public static void EncryptAndSign(string inputFile, string outputFile, string publicKeyFile, string privateKeyFile, string passPhrase, bool armor)
{
PgpEncryptionKeys encryptionKeys = new PgpEncryptionKeys(publicKeyFile, privateKeyFile, passPhrase);

if (!File.Exists(inputFile))
throw new FileNotFoundException(String.Format("Input file [{0}] does not exist.", inputFile));

if (!File.Exists(publicKeyFile))
throw new FileNotFoundException(String.Format("Public Key file [{0}] does not exist.", publicKeyFile));

if (!File.Exists(privateKeyFile))
throw new FileNotFoundException(String.Format("Private Key file [{0}] does not exist.", privateKeyFile));

if (String.IsNullOrEmpty(passPhrase))
throw new ArgumentNullException("Invalid Pass Phrase.");

if (encryptionKeys == null)
throw new ArgumentNullException("Encryption Key not found.");

using (Stream outputStream = File.Create(outputFile))
{
if (armor)
using (ArmoredOutputStream armoredOutputStream = new ArmoredOutputStream(outputStream))
{
OutputEncrypted(inputFile, armoredOutputStream, encryptionKeys);
}
else
OutputEncrypted(inputFile, outputStream, encryptionKeys);
}
}

private static void OutputEncrypted(string inputFile, Stream outputStream, PgpEncryptionKeys encryptionKeys)
{
using (Stream encryptedOut = ChainEncryptedOut(outputStream, encryptionKeys))
{
FileInfo unencryptedFileInfo = new FileInfo(inputFile);
using (Stream compressedOut = ChainCompressedOut(encryptedOut))
{
PgpSignatureGenerator signatureGenerator = InitSignatureGenerator(compressedOut, encryptionKeys);
using (Stream literalOut = ChainLiteralOut(compressedOut, unencryptedFileInfo))
{
using (FileStream inputFileStream = unencryptedFileInfo.OpenRead())
{
WriteOutputAndSign(compressedOut, literalOut, inputFileStream, signatureGenerator);
inputFileStream.Close();
}
}
}
}
}

private static void WriteOutputAndSign(Stream compressedOut, Stream literalOut, FileStream inputFile, PgpSignatureGenerator signatureGenerator)
{
int length = 0;
byte[] buf = new byte[BufferSize];
while ((length = inputFile.Read(buf, 0, buf.Length)) > 0)
{
literalOut.Write(buf, 0, length);
signatureGenerator.Update(buf, 0, length);
}
signatureGenerator.Generate().Encode(compressedOut);
}

private static Stream ChainEncryptedOut(Stream outputStream, PgpEncryptionKeys m_encryptionKeys)
{
PgpEncryptedDataGenerator encryptedDataGenerator;
encryptedDataGenerator = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.TripleDes, new SecureRandom());
encryptedDataGenerator.AddMethod(m_encryptionKeys.PublicKey);
return encryptedDataGenerator.Open(outputStream, new byte[BufferSize]);
}

private static Stream ChainCompressedOut(Stream encryptedOut)
{
PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
return compressedDataGenerator.Open(encryptedOut);
}

private static Stream ChainLiteralOut(Stream compressedOut, FileInfo file)
{
PgpLiteralDataGenerator pgpLiteralDataGenerator = new PgpLiteralDataGenerator();
return pgpLiteralDataGenerator.Open(compressedOut, PgpLiteralData.Binary, file);
}

private static PgpSignatureGenerator InitSignatureGenerator(Stream compressedOut, PgpEncryptionKeys m_encryptionKeys)
{
const bool IsCritical = false;
const bool IsNested = false;
PublicKeyAlgorithmTag tag = m_encryptionKeys.SecretKey.PublicKey.Algorithm;
PgpSignatureGenerator pgpSignatureGenerator = new PgpSignatureGenerator(tag, HashAlgorithmTag.Sha1);
pgpSignatureGenerator.InitSign(PgpSignature.BinaryDocument, m_encryptionKeys.PrivateKey);
foreach (string userId in m_encryptionKeys.SecretKey.PublicKey.GetUserIds())
{
PgpSignatureSubpacketGenerator subPacketGenerator = new PgpSignatureSubpacketGenerator();
subPacketGenerator.SetSignerUserId(IsCritical, userId);
pgpSignatureGenerator.SetHashedSubpackets(subPacketGenerator.Generate());
// Just the first one!
break;
}
pgpSignatureGenerator.GenerateOnePassVersion(IsNested).Encode(compressedOut);
return pgpSignatureGenerator;
}

#endregion Encrypt and Sign

#region Decrypt

/*
* decrypt a given stream.
*/

public static void Decrypt(string inputfile, string privateKeyFile, string passPhrase, string outputFile)
{
if (!File.Exists(inputfile))
throw new FileNotFoundException(String.Format("Encrypted File [{0}] not found.", inputfile));

if (!File.Exists(privateKeyFile))
throw new FileNotFoundException(String.Format("Private Key File [{0}] not found.", privateKeyFile));

if (String.IsNullOrEmpty(outputFile))
throw new ArgumentNullException("Invalid Output file path.");

using (Stream inputStream = File.OpenRead(inputfile))
{
using (Stream keyIn = File.OpenRead(privateKeyFile))
{
Decrypt(inputStream, keyIn, passPhrase, outputFile);
}
}
}

/*
* decrypt a given stream.
*/

public static void Decrypt(Stream inputStream, Stream privateKeyStream, string passPhrase, string outputFile)
{
try
{
PgpObjectFactory pgpF = null;
PgpEncryptedDataList enc = null;
PgpObject o = null;
PgpPrivateKey sKey = null;
PgpPublicKeyEncryptedData pbe = null;
PgpSecretKeyRingBundle pgpSec = null;

pgpF = new PgpObjectFactory(PgpUtilities.GetDecoderStream(inputStream));
// find secret key
pgpSec = new PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(privateKeyStream));

if (pgpF != null)
o = pgpF.NextPgpObject();

// the first object might be a PGP marker packet.
if (o is PgpEncryptedDataList)
enc = (PgpEncryptedDataList)o;
else
enc = (PgpEncryptedDataList)pgpF.NextPgpObject();

// decrypt
foreach (PgpPublicKeyEncryptedData pked in enc.GetEncryptedDataObjects())
{
sKey = FindSecretKey(pgpSec, pked.KeyId, passPhrase.ToCharArray());

if (sKey != null)
{
pbe = pked;
break;
}
}

if (sKey == null)
throw new ArgumentException("Secret key for message not found.");

PgpObjectFactory plainFact = null;

using (Stream clear = pbe.GetDataStream(sKey))
{
plainFact = new PgpObjectFactory(clear);
}

PgpObject message = plainFact.NextPgpObject();

if (message is PgpCompressedData)
{
PgpCompressedData cData = (PgpCompressedData)message;
PgpObjectFactory of = null;

using (Stream compDataIn = cData.GetDataStream())
{
of = new PgpObjectFactory(compDataIn);
}

message = of.NextPgpObject();
if (message is PgpOnePassSignatureList)
{
message = of.NextPgpObject();
PgpLiteralData Ld = null;
Ld = (PgpLiteralData)message;
using (Stream output = File.Create(outputFile))
{
Stream unc = Ld.GetInputStream();
Streams.PipeAll(unc, output);
}
}
else
{
PgpLiteralData Ld = null;
Ld = (PgpLiteralData)message;
using (Stream output = File.Create(outputFile))
{
Stream unc = Ld.GetInputStream();
Streams.PipeAll(unc, output);
}
}
}
else if (message is PgpLiteralData)
{
PgpLiteralData ld = (PgpLiteralData)message;
string outFileName = ld.FileName;

using (Stream fOut = File.Create(outputFile))
{
Stream unc = ld.GetInputStream();
Streams.PipeAll(unc, fOut);
}
}
else if (message is PgpOnePassSignatureList)
throw new PgpException("Encrypted message contains a signed message - not literal data.");
else
throw new PgpException("Message is not a simple encrypted file - type unknown.");

#region commented code

//if (pbe.IsIntegrityProtected())
//{
// if (!pbe.Verify())
// msg = "message failed integrity check.";
// //Console.Error.WriteLine("message failed integrity check");
// else
// msg = "message integrity check passed.";
// //Console.Error.WriteLine("message integrity check passed");
//}
//else
//{
// msg = "no message integrity check.";
// //Console.Error.WriteLine("no message integrity check");
//}

#endregion commented code
}
catch (PgpException ex)
{
throw;
}
}

#endregion Decrypt

#region Private helpers

/*
* A simple routine that opens a key ring file and loads the first available key suitable for encryption.
*/

private static PgpPublicKey ReadPublicKey(Stream inputStream)
{
inputStream = PgpUtilities.GetDecoderStream(inputStream);

PgpPublicKeyRingBundle pgpPub = new PgpPublicKeyRingBundle(inputStream);

// we just loop through the collection till we find a key suitable for encryption, in the real
// world you would probably want to be a bit smarter about this.
// iterate through the key rings.
foreach (PgpPublicKeyRing kRing in pgpPub.GetKeyRings())
{
foreach (PgpPublicKey k in kRing.GetPublicKeys())
{
if (k.IsEncryptionKey)
return k;
}
}

throw new ArgumentException("Can't find encryption key in key ring.");
}

/*
* Search a secret key ring collection for a secret key corresponding to keyId if it exists.
*/

private static PgpPrivateKey FindSecretKey(PgpSecretKeyRingBundle pgpSec, long keyId, char[] pass)
{
PgpSecretKey pgpSecKey = pgpSec.GetSecretKey(keyId);

if (pgpSecKey == null)
return null;

return pgpSecKey.ExtractPrivateKey(pass);
}

#endregion Private helpers
}
}

它使用:

using System;
using System.IO;
using System.Linq;
using Org.BouncyCastle.Bcpg.OpenPgp;

namespace FileEncryptionTasks.Helpers.PGP
{
public class PgpEncryptionKeys
{
public PgpPublicKey PublicKey { get; private set; }

public PgpPrivateKey PrivateKey { get; private set; }

public PgpSecretKey SecretKey { get; private set; }

/// <summary>
/// Initializes a new instance of the EncryptionKeys class.
/// Two keys are required to encrypt and sign data. Your private key and the recipients public key.
/// The data is encrypted with the recipients public key and signed with your private key.
/// </summary>
/// <param name="publicKeyPath">The key used to encrypt the data</param>
/// <param name="privateKeyPath">The key used to sign the data.</param>
/// <param name="passPhrase">The (your) password required to access the private key</param>
/// <exception cref="ArgumentException">Public key not found. Private key not found. Missing password</exception>
public PgpEncryptionKeys(string publicKeyPath, string privateKeyPath, string passPhrase)
{
if (!File.Exists(publicKeyPath))
throw new ArgumentException("Public key file not found", "publicKeyPath");
if (!File.Exists(privateKeyPath))
throw new ArgumentException("Private key file not found", "privateKeyPath");
if (String.IsNullOrEmpty(passPhrase))
throw new ArgumentException("passPhrase is null or empty.", "passPhrase");
PublicKey = ReadPublicKey(publicKeyPath);
SecretKey = ReadSecretKey(privateKeyPath);
PrivateKey = ReadPrivateKey(passPhrase);
}

#region Secret Key

private PgpSecretKey ReadSecretKey(string privateKeyPath)
{
using (Stream keyIn = File.OpenRead(privateKeyPath))
{
using (Stream inputStream = PgpUtilities.GetDecoderStream(keyIn))
{
PgpSecretKeyRingBundle secretKeyRingBundle = new PgpSecretKeyRingBundle(inputStream);
PgpSecretKey foundKey = GetFirstSecretKey(secretKeyRingBundle);
if (foundKey != null)
return foundKey;
}
}
throw new ArgumentException("Can't find signing key in key ring.");
}

/// <summary>
/// Return the first key we can use to encrypt.
/// Note: A file can contain multiple keys (stored in "key rings")
/// </summary>
private PgpSecretKey GetFirstSecretKey(PgpSecretKeyRingBundle secretKeyRingBundle)
{
foreach (PgpSecretKeyRing kRing in secretKeyRingBundle.GetKeyRings())
{
PgpSecretKey key = kRing.GetSecretKeys()
.Cast<PgpSecretKey>()
.Where(k => k.IsSigningKey)
.FirstOrDefault();
if (key != null)
return key;
}
return null;
}

#endregion Secret Key

#region Public Key

private PgpPublicKey ReadPublicKey(string publicKeyPath)
{
using (Stream keyIn = File.OpenRead(publicKeyPath))
{
using (Stream inputStream = PgpUtilities.GetDecoderStream(keyIn))
{
PgpPublicKeyRingBundle publicKeyRingBundle = new PgpPublicKeyRingBundle(inputStream);
PgpPublicKey foundKey = GetFirstPublicKey(publicKeyRingBundle);
if (foundKey != null)
return foundKey;
}
}
throw new ArgumentException("No encryption key found in public key ring.");
}

private PgpPublicKey GetFirstPublicKey(PgpPublicKeyRingBundle publicKeyRingBundle)
{
foreach (PgpPublicKeyRing kRing in publicKeyRingBundle.GetKeyRings())
{
PgpPublicKey key = kRing.GetPublicKeys()
.Cast<PgpPublicKey>()
.Where(k => k.IsEncryptionKey)
.FirstOrDefault();
if (key != null)
return key;
}
return null;
}

#endregion Public Key

#region Private Key

private PgpPrivateKey ReadPrivateKey(string passPhrase)
{
PgpPrivateKey privateKey = SecretKey.ExtractPrivateKey(passPhrase.ToCharArray());
if (privateKey != null)
return privateKey;
throw new ArgumentException("No private key found in secret key.");
}

#endregion Private Key
}
}

加密文件:

PGPEncryptDecrypt.EncryptFile(inputFileName, 
outputFileName,
recipientKeyFileName,
shouldArmor,
shouldCheckIntegrity);

解密文件:

PGPEncryptDecrypt.Decrypt(inputFileName, 
privateKeyFileName,
passPhrase,
outputFileName);

关于c# - PGP 加密和解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10209291/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com