加解密专辑对接触到的PGPRSAAES加解密算法整理
Posted 多安分
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了加解密专辑对接触到的PGPRSAAES加解密算法整理相关的知识,希望对你有一定的参考价值。
先贴代码,有空再整理思路
PGP加密
using System; using System.IO; using Org.BouncyCastle.Bcpg; using Org.BouncyCastle.Bcpg.OpenPgp; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities.IO; using System.Linq; namespace Server5.V2.Common { public static class PGPEncryptDecrypt { static void test() { var inputFileName = ""; var outputFileName = ""; var recipientKeyFileName = ""; var shouldArmor = false; var shouldCheckIntegrity = false; //Encrypt a file: PGPEncryptDecrypt.EncryptFile(inputFileName, outputFileName, recipientKeyFileName, shouldArmor, shouldCheckIntegrity); var privateKeyFileName = ""; var passPhrase = ""; //Decrypt a file: PGPEncryptDecrypt.Decrypt(inputFileName, privateKeyFileName, passPhrase, outputFileName); } 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 } 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(file.FullName, file.FullName + ".DAT", "D:\\\\test\\\\key\\\\dsfpublic.asc", false, false); PGPEncryptDecrypt.Decrypt(file.FullName + ".DAT", "D:\\\\test\\\\key\\\\dsfsecret.asc", "mon123day", file.FullName + ".ZIP");
测试代码
static void test() { var inputFileName = ""; var outputFileName = ""; var recipientKeyFileName = ""; var shouldArmor = false; var shouldCheckIntegrity = false; //Encrypt a file: PGPEncryptDecrypt.EncryptFile(inputFileName, outputFileName, recipientKeyFileName, shouldArmor, shouldCheckIntegrity); var privateKeyFileName = ""; var passPhrase = ""; //Decrypt a file: PGPEncryptDecrypt.Decrypt(inputFileName, privateKeyFileName, passPhrase, outputFileName); }
RSA加密
using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; namespace Server5.V2.Common { /// <summary> /// 非对称RSA加密类 可以参考 /// http://www.cnblogs.com/hhh/archive/2011/06/03/2070692.html /// http://blog.csdn.net/zhilunchen/article/details/2943158 /// 若是私匙加密 则需公钥解密 /// 反正公钥加密 私匙来解密 /// 需要BigInteger类来辅助 /// </summary> public static class RSAHelper { static void test() { string str = "{\\"sc\\":\\"his51\\",\\"no\\":\\"1\\",\\"na\\":\\"管理员\\"}"; System.Diagnostics.Debug.Print("明文:\\r\\n" + str + "\\r\\n"); RSAHelper.RSAKey keyPair = RSAHelper.GetRASKey(); System.Diagnostics.Debug.Print("公钥:\\r\\n" + keyPair.PublicKey + "\\r\\n"); System.Diagnostics.Debug.Print("私钥:\\r\\n" + keyPair.PrivateKey + "\\r\\n"); string en = RSAHelper.EncryptString(str, keyPair.PrivateKey); System.Diagnostics.Debug.Print("公钥加密后:\\r\\n" + en + "\\r\\n"); var de = RSAHelper.DecryptString(en, keyPair.PublicKey); System.Diagnostics.Debug.Print("解密:\\r\\n" + de + "\\r\\n"); Console.ReadKey(); } /// <summary> /// RSA的容器 可以解密的源字符串长度为 DWKEYSIZE/8-11 /// </summary> public const int DWKEYSIZE = 1024; /// <summary> /// RSA加密的密匙结构 公钥和私匙 /// </summary> public struct RSAKey { public string PublicKey { get; set; } public string PrivateKey { get; set; } } #region 得到RSA的解谜的密匙对 /// <summary以上是关于加解密专辑对接触到的PGPRSAAES加解密算法整理的主要内容,如果未能解决你的问题,请参考以下文章