/// <summary> /// Verifies clear text PGP signature. See documentation at https://github.com/CommunityHiQ/Frends.Community.PgpVerifyClearTextSignature Returns: Object {string FilePath, Boolean Verified} /// </summary> public static PgpVerifyClearTextSignatureResult VerifyFileClearTextSignature(PgpVerifyClearTextSignatureInput input) { using (var inStr = File.OpenRead(input.InputFile)) using (var outStr = File.Create(input.OutputFile)) using (var keyStr = PgpUtilities.GetDecoderStream(File.OpenRead(input.PublicKeyFile))) { var aInputStr = new ArmoredInputStream(inStr); // // write out signed section using the local line separator. // note: trailing white space needs to be removed from the end of // each line RFC 4880 Section 7.1 // var lineOut = new MemoryStream(); var lookAhead = PgpServices.VerifyClearTextSignatureReadInputLine(lineOut, aInputStr); var lineSep = Encoding.ASCII.GetBytes(Environment.NewLine); if (lookAhead != -1 && aInputStr.IsClearText()) { var line = lineOut.ToArray(); outStr.Write(line, 0, PgpServices.GetLengthWithoutSeparatorOrTrailingWhitespace(line)); outStr.Write(lineSep, 0, lineSep.Length); while (lookAhead != -1 && aInputStr.IsClearText()) { lookAhead = PgpServices.VerifyClearTextSignatureReadInputLine(lineOut, lookAhead, aInputStr); line = lineOut.ToArray(); outStr.Write(line, 0, PgpServices.GetLengthWithoutSeparatorOrTrailingWhitespace(line)); outStr.Write(lineSep, 0, lineSep.Length); } } else { // a single line file if (lookAhead != -1) { var line = lineOut.ToArray(); outStr.Write(line, 0, PgpServices.GetLengthWithoutSeparatorOrTrailingWhitespace(line)); outStr.Write(lineSep, 0, lineSep.Length); } } outStr.Close(); var pgpRings = new PgpPublicKeyRingBundle(keyStr); var pgpFact = new PgpObjectFactory(aInputStr); var p3 = (PgpSignatureList)pgpFact.NextPgpObject(); var sig = p3[0]; inStr.Close(); sig.InitVerify(pgpRings.GetPublicKey(sig.KeyId)); // read the input, making sure we ignore the last newline. bool verified; using (var sigIn = File.OpenRead(input.OutputFile)) { lookAhead = PgpServices.VerifyClearTextSignatureReadInputLine(lineOut, sigIn); PgpServices.ProcessLine(sig, lineOut.ToArray()); while (lookAhead != -1) { lookAhead = PgpServices.VerifyClearTextSignatureReadInputLine(lineOut, lookAhead, sigIn); sig.Update((byte)'\r'); sig.Update((byte)'\n'); PgpServices.ProcessLine(sig, lineOut.ToArray()); } verified = sig.Verify(); sigIn.Close(); } var ret = new PgpVerifyClearTextSignatureResult { FilePath = input.OutputFile, Verified = verified }; return(ret); } }
/// <summary> /// Create a file with PGP clear text signature. See documentation at https://github.com/CommunityHiQ/Frends.Community.PgpClearTextSignature Returns: Object {string FilePath} /// </summary> public static PgpClearTextSignatureResult ClearTextSignFile(PgpClearTextSignatureInput input) { HashAlgorithmTag digest; switch (input.HashFunction) { case PgpClearTextSignatureHashFunctionType.Md5: digest = HashAlgorithmTag.MD5; break; case PgpClearTextSignatureHashFunctionType.RipeMd160: digest = HashAlgorithmTag.RipeMD160; break; case PgpClearTextSignatureHashFunctionType.Sha1: digest = HashAlgorithmTag.Sha1; break; case PgpClearTextSignatureHashFunctionType.Sha224: digest = HashAlgorithmTag.Sha224; break; case PgpClearTextSignatureHashFunctionType.Sha384: digest = HashAlgorithmTag.Sha384; break; case PgpClearTextSignatureHashFunctionType.Sha512: digest = HashAlgorithmTag.Sha512; break; case PgpClearTextSignatureHashFunctionType.Sha256: digest = HashAlgorithmTag.Sha256; break; default: digest = HashAlgorithmTag.Sha256; break; } var privateKeyStream = File.OpenRead(input.PrivateKeyFile); var pgpSecKey = PgpServices.ReadSecretKey(privateKeyStream); var pgpPrivKey = pgpSecKey.ExtractPrivateKey(input.Password.ToCharArray()); var sGen = new PgpSignatureGenerator(pgpSecKey.PublicKey.Algorithm, digest); var spGen = new PgpSignatureSubpacketGenerator(); sGen.InitSign(PgpSignature.CanonicalTextDocument, pgpPrivKey); var enumerator = pgpSecKey.PublicKey.GetUserIds().GetEnumerator(); if (enumerator.MoveNext()) { spGen.SetSignerUserId(false, (string)enumerator.Current); sGen.SetHashedSubpackets(spGen.Generate()); } var fIn = File.OpenRead(input.InputFile); var outputStream = File.Create(input.OutputFile); var aOut = new ArmoredOutputStream(outputStream); aOut.BeginClearText(digest); // // note the last \n/\r/\r\n in the file is ignored // var lineOut = new MemoryStream(); var lookAhead = PgpServices.ReadInputLine(lineOut, fIn); PgpServices.ProcessLine(aOut, sGen, lineOut.ToArray()); while (lookAhead != -1) { lookAhead = PgpServices.ReadInputLine(lineOut, lookAhead, fIn); sGen.Update((byte)'\r'); sGen.Update((byte)'\n'); PgpServices.ProcessLine(aOut, sGen, lineOut.ToArray()); } fIn.Close(); aOut.EndClearText(); var bOut = new BcpgOutputStream(aOut); sGen.Generate().Encode(bOut); aOut.Close(); outputStream.Close(); var ret = new PgpClearTextSignatureResult { FilePath = input.OutputFile }; return(ret); }