/*.......................................................................數位簽章開始*/ private static void SignFile( string fileName, //欲作簽章的檔案名稱及位置 Stream keyIn, // Private key 的 File Stream Stream outputStream, //簽章後的檔案 File Stream char[] pass, // private Key 的 password bool armor, //用途不明?? 範例預設true bool compress //用途不明?? 範例預設true ) { if (armor) { outputStream = new ArmoredOutputStream(outputStream); } PgpSecretKey pgpSec = PgpExampleUtilities.ReadSecretKey(keyIn); PgpPrivateKey pgpPrivKey = pgpSec.ExtractPrivateKey(pass); PgpSignatureGenerator sGen = new PgpSignatureGenerator(pgpSec.PublicKey.Algorithm, HashAlgorithmTag.Sha256); 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(); } }
/*.......................................................................加密開始*/ /*文章 -> Session Key(對稱式) - > 文章加密 - - - - - -> 加密後的文章 * -> Session Key(對稱式) - > 公鑰(對方)加密 - - -> 加密後的Session Key */ //外部呼叫的 method public static void EncryptFile( string outputFileName, //加密後輸出檔案名稱位置 string inputFileName, //欲加密檔案名稱位置 string encKeyFileName, //提供加密的 public key(接收方的) 檔名及位置 bool armor, //盔甲??,範例預設為true bool withIntegrityCheck //完整性檢查,範例預設為false ) { PgpPublicKey encKey = PgpExampleUtilities.ReadPublicKey(encKeyFileName); //find encryption key using (Stream output = File.Create(outputFileName)) { EncryptFile(output, inputFileName, encKey, armor, withIntegrityCheck); } }
/*文章 -> Session Key(對稱式) - > 文章加密 - - - - - -> 加密後的文章 * -> Session Key(對稱式) - > 公鑰(對方)加密 - - -> 加密後的Session Key */ //內部的實作參照官方範例 private static void EncryptFile( Stream outputStream, //加密後輸出檔案之資料流 string fileName, //欲加密檔案名稱位置 PgpPublicKey encKey, //接收方的公鑰(對方) bool armor, bool withIntegrityCheck /*完整性檢查*/) { if (armor) { outputStream = new ArmoredOutputStream(outputStream); //位置、headers、雜湊表 } try { byte[] bytes = PgpExampleUtilities.CompressFile(fileName, CompressionAlgorithmTag.Zip); //資料壓縮一個檔案 PgpEncryptedDataGenerator encGen = new PgpEncryptedDataGenerator( SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom()); //隨機產生Session Key(對稱-Cast5) encGen.AddMethod(encKey); Stream cOut = encGen.Open(outputStream, bytes.Length); //建立 todo 注意,RSA非對稱加密,公鑰加密私鑰解密,預設為SHA1,但可選擇 SHA256雜湊 cOut.Write(bytes, 0, bytes.Length); //加密及寫入 cOut.Close(); if (armor) { outputStream.Close(); outputStream.Dispose(); } } catch (PgpException e) { Console.Error.WriteLine(e); Exception underlyingException = e.InnerException; if (underlyingException != null) { Console.Error.WriteLine(underlyingException.Message); Console.Error.WriteLine(underlyingException.StackTrace); } } }
//內部的實作參照官方範例 private static void EncryptFile( Stream outputStream, string fileName, PgpPublicKey encKey, bool armor, bool withIntegrityCheck) { if (armor) { outputStream = new ArmoredOutputStream(outputStream); } try { byte[] bytes = PgpExampleUtilities.CompressFile(fileName, CompressionAlgorithmTag.Zip); PgpEncryptedDataGenerator encGen = new PgpEncryptedDataGenerator( SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom()); encGen.AddMethod(encKey); Stream cOut = encGen.Open(outputStream, bytes.Length); cOut.Write(bytes, 0, bytes.Length); cOut.Close(); if (armor) { outputStream.Close(); } } catch (PgpException e) { Console.Error.WriteLine(e); Exception underlyingException = e.InnerException; if (underlyingException != null) { Console.Error.WriteLine(underlyingException.Message); Console.Error.WriteLine(underlyingException.StackTrace); } } }
/* * 文章 -> hash -> 私鑰(自己)簽章 -> 簽章後的hash值 * 文章 - - - - - - - - - - - - - -> 文章 */ /*.......................................................................數位簽章開始*/ private static void SignFile( string fileName, //預計數位簽章原始檔案的完整路徑 Stream keyIn, // Private key 的 File Stream (自己) Stream outputStream, //預計匯出(數位簽章後) File Stream char[] pass, // private Key 的 password bool armor, //盔甲??? 範例預設true bool compress //解壓縮 範例預設true ) { if (armor) { outputStream = new ArmoredOutputStream(outputStream); //匯出位置、headers、雜湊表 } PgpSecretKey pgpSec = PgpExampleUtilities.ReadSecretKey(keyIn); //PgpSecretKey包含私鑰及公鑰整個物件 PgpPrivateKey pgpPrivKey = pgpSec.ExtractPrivateKey(pass); //需輸入私鑰密碼才能取出私鑰 /* * SHA是由美國國家安全局制定,主要應用於數字簽名標準裡面的數字簽名算法( DSA : Digital Signature Algorithm ), * SHA家族中以SHA1和SHA256最為廣泛使用。SHA1的雜湊值長度為160bit、SHA256則為256bit,長度越長碰撞的機會就越低也越安全, * 但同時計算的時間複雜度也隨著增高。 */ PgpSignatureGenerator sGen = new PgpSignatureGenerator(pgpSec.PublicKey.Algorithm, HashAlgorithmTag.Sha256); //PublicKey.Algorithm即原始公鑰 sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey); //若沒私鑰重新生產一個 foreach (string userId in pgpSec.PublicKey.GetUserIds()) //ExportKeyPair 的 identity (MarkWu) { PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(); spGen.SetSignerUserId(false, userId); //數位簽章的使用者 sGen.SetHashedSubpackets(spGen.Generate()); //將 SignatureSubpacket 陣列化再回傳 // 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); //hash 加密 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(); } }
/* * 加密後的Session Key -> 私鑰(自己)解密 -> Session Key(對稱式) * 加密後的文章 - - - - - - - - - - - - - > Session Key(對稱式) -> 解密後的文章 */ private static void DecryptFile( Stream inputStream, //欲解密之檔案之串流 Stream keyIn, //私鑰之串流 char[] passwd, //私鑰密碼 string defaultFileName //解密後檔案名稱及位置 ) { inputStream = PgpUtilities.GetDecoderStream(inputStream); //資料流陣列化 byte Array try { PgpObjectFactory pgpF = new PgpObjectFactory(inputStream); PgpEncryptedDataList enc; PgpObject o = pgpF.NextPgpObject(); // // the first object might be a PGP marker packet. // if (o is PgpEncryptedDataList) { enc = (PgpEncryptedDataList)o; } else { enc = (PgpEncryptedDataList)pgpF.NextPgpObject(); } // // find the Secret Key // PgpPrivateKey sKey = null; PgpPublicKeyEncryptedData pbe = null; PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle( PgpUtilities.GetDecoderStream(keyIn)); //new 密鑰捆包 物件 foreach (PgpPublicKeyEncryptedData pked in enc.GetEncryptedDataObjects()) { sKey = PgpExampleUtilities.FindSecretKey(pgpSec, pked.KeyId, passwd); //(密鑰捆包,identify,私鑰密碼),抓對稱加密的密鑰,密鑰 if (sKey != null) { pbe = pked; break; } } if (sKey == null) { throw new ArgumentException("secret key for message not found."); } Stream clear = pbe.GetDataStream(sKey); //解碼 PgpObjectFactory plainFact = new PgpObjectFactory(clear); // BcpgInputStream PgpObject message = plainFact.NextPgpObject(); //取出 if (message is PgpCompressedData) { PgpCompressedData cData = (PgpCompressedData)message; PgpObjectFactory pgpFact = new PgpObjectFactory(cData.GetDataStream()); message = pgpFact.NextPgpObject(); //解壓縮 } if (message is PgpLiteralData) { PgpLiteralData ld = (PgpLiteralData)message; //內容 string outFileName = ld.FileName; //if (outFileName.Length == 0) //{ outFileName = defaultFileName; //} Stream fOut = File.Create(outFileName); Stream unc = ld.GetInputStream(); Streams.PipeAll(unc, fOut); //Pipe一種傳輸方式,存入匯出檔案 fOut.Close(); fOut.Dispose(); } 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."); } if (pbe.IsIntegrityProtected()) { if (!pbe.Verify()) { Console.Error.WriteLine("message failed integrity check"); } else { Console.Error.WriteLine("message integrity check passed"); } } else { Console.Error.WriteLine("no message integrity check"); } } catch (PgpException e) { Console.Error.WriteLine(e); Exception underlyingException = e.InnerException; if (underlyingException != null) { Console.Error.WriteLine(underlyingException.Message); Console.Error.WriteLine(underlyingException.StackTrace); } } }