2011-07-10 15 views
1

私は以下のメッセージを確認するだけですが、Bouncy Castleにデータを取り込んで公開鍵を与えてもメッセージを確認することはできません。私はそれが自由であれば使用される他のリブになるのがうれしいです。これは、インターネット上でデータを受け取る私のアプリに組み込まれているので、可能な限りすべてのマネージコードを保持したいと考えています。Bouncy Castleまたは他のC#ライブラリを使用してC#でこのPGPメッセージを確認する方法

-----BEGIN PGP SIGNED MESSAGE----- 
Hash: SHA1 

SCI Version: 1.0 
SCI Code: 1 
SCI Reason: OK 
SCI Balance: 0.00050000 

-----BEGIN PGP SIGNATURE----- 
Version: GnuPG/MBC v1.0 

iQEcBAEBAgAGBQJOGSuYAAoJEJ+5g06lAnqFkdsH/0NoqQbNvR8ZPe8D4gL4gvff 
6K1t2LOt0sQGj+RSPeEbag7ZnVNI65LiES/yie1N6cXMkFgb9/ttjxi9/wlbxD/j 
gSkuZ6mT9Oc5ExLsRZq9ygytvVs7Ol7uQm6oxDzJX1JMs0ls2EwJbmmpTEOHn8Av 
dGlxdZeh+3RlqHJmOdssQCJ0cw5VXuj5vfP35OYz2zO2+sNg0eCXdR5Ml+2S7n3U 
n9VHPEECg72LvpxF/y/nApopXoHpwECXoBwHgyd9QIIw1IJgalyRLDmAJ2WXdROV 
ln2Mkt/km3KtBS3h4QL407wi/KhgZ4tFohZupt7zq2zUwtHWOhbL2KSUu939OKk= 
=mIjM 
-----END PGP SIGNATURE----- 

答えて

4

興味のある人には、BouncyCastleソースコードのこの正確なタスクの例が見つかりました。サンプルを入手するには、バイナリではなくソースコードをダウンロードする必要があります。また、OpenPGPのさまざまなユースケースすべての例があるようです。

+0

ありがとうx1,000,000、私はX509の署名ではなく、PGPに精通することだし、それは誰も望んでいないようですStackExchangeでこれを行うには、公開鍵を使用して暗号化に関する記事を検索し、非公開を使用して署名しないでください。 – StrangeWill

+0

これは、Seerが話している例だと思います。 https://github.com/bcgit/bc-csharp/blob/master/crypto/test/src/openpgp/examples/ClearSignedFileProcessor.cs –

1
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]"); 
      } 
     } 
    } 
} 
0

Seerさんの提案に続いてthis exampleのメッセージが表示されました。

私はメソッドVerifyFileを持っています。このメソッドは、署名されたメッセージと公開鍵を受け取り、検証に合格するとメッセージの内容を返します。例えば、それはこのように使用することができます:

string key = @"-----BEGIN PGP PUBLIC KEY BLOCK----- 
Version: BCPG C# v1.6.1.0 

mQENBFpc87wBCACK5FG6Z70iovzSzQF7OEB/YbKF7SPS1/GZAQhp/2n2G8x5Lxj5 
/CKqR8JLj1+222unuWgfqvfny0fLvttt1r6lAH/kqDYMBg26GTbZy93R5BYatBjd 
pzYl/lIyKxc/QwDdZm8zNxeUpDSfoe9jVULOg0MiMDtdQupOf6CanlEioXfyf88F 
1BLcJyFSckaYieosBw5hnnI+1cZZ3k+4HpDJJslVzngfTPWRibtN5PKff1CKP55E 
ME99XkuPDaNL7XZmu7lZSEUN3jJFVydZQrDkvxddihzV4pTgRI3gDAFoJxxIYZX3 
JsQAJItlqq8bBsQ+bKPikgAiMySGcEi+ilI5ABEBAAG0GnNoYWxhbWFub3YubWFy 
aW5AZ21haWwuY29tiQEcBBABAgAGBQJaXPO8AAoJEBvHdfmVFHzkvHEH/179VAdH 
gWRN5HVprsp4vHP3q1CJV9j+fPlQIZU3JEwrM+INxzpfSqZeN4NwB7yoo2NCdCNP 
Ndg8zhiuEYM51hNtqU5cwYBcaAbm1so6TSVo8i4nrfN3+oDYEfYPqglNrd1V233J 
oyLriwpGkR6RBYMY2q2Re+EFNR1bxUmeE0wnb8FOodRCSh0Wd3Iy9mvmhv5voHIr 
aZzgsuifGw1JilSu9+RoC6b1CHb9jUkWQ/odkTvl5/rxA14TKstgoLoSLHktYQfw 
le6B8+lPtmODtagWoDEeR/M0zm/wyCOt5wqjjJCgvaipUaA+oiijIYwCpqUBwfm3 
DZ9DStGHGVxQQnc= 
=s91O 
-----END PGP PUBLIC KEY BLOCK----- 
"; 
string message = @"-----BEGIN PGP SIGNED MESSAGE----- 
Hash: SHA256 

test tes tes ts tse tse t 
-----BEGIN PGP SIGNATURE----- 
Version: OpenPGP.js v1.0.1 
Comment: http://openpgpjs.org 

wsBcBAEBCAAQBQJaXP5WCRAbx3X5lRR85AAAUcoH/jtcyWcpTVyXyz/ptWLo 
Hx+g51EeeA0Hpq7kZCXu4FuyhNn/QvnvKyt9qegxQoRSZhT37ln8t80NW6sS 
B4XVFziq8TBkjPuaYBI/ijbLigdPMEi81PsOpIXx3BXKCt27TLmUVHpFTWPa 
u2NQUQl3k3Xc0H1sy1A+jmjfvCyqWxTOU1IY4rlzRKHdp+D1oCz5iKfyfUko 
ktAZgqOMx5pWL975YhM793MS8aYqhOdQpeuW401fm18xxwE4x6svSSys+qq8 
MdkL/i7YVjUKr/M8SIrGPb/IjKwClM7jfpN+sHv0p/GcQ7J1kmXYUdA6AJp5 
Z0vYk4aPcMSlrPwdRX21I9w= 
=zXfe 
-----END PGP SIGNATURE----- 
"; 

MemoryStream messageStream = new MemoryStream(Encoding.ASCII.GetBytes(message)); 
MemoryStream keyStream = new MemoryStream(Encoding.ASCII.GetBytes(key)); 

try { 
    var msg= VerifyFile(messageStream, 
      PgpUtilities.GetDecoderStream(keyStream)); 
    // verification passes msg is the content of the message 
} catch (Exception e) { 
    // verification fails 
} 

をそして、ここで実装したものです:

private static String VerifyFile(Stream inputStream, Stream keyIn) 
    { 
     ArmoredInputStream aIn = new ArmoredInputStream(inputStream); 
     MemoryStream outStr = new MemoryStream(); // File.Create(resultName); 


     // 
     // 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 
     // 
     MemoryStream lineOut = new MemoryStream(); 
     int lookAhead = ReadInputLine(lineOut, aIn); 
     byte[] lineSep = LineSeparator; 

     if (lookAhead != -1 && aIn.IsClearText()) 
     { 
      byte[] line = lineOut.ToArray(); 
      outStr.Write(line, 0, GetLengthWithoutSeparatorOrTrailingWhitespace(line)); 
      outStr.Write(lineSep, 0, lineSep.Length); 

      while (lookAhead != -1 && aIn.IsClearText()) 
      { 
       lookAhead = ReadInputLine(lineOut, lookAhead, aIn); 

       line = lineOut.ToArray(); 
       outStr.Write(line, 0, GetLengthWithoutSeparatorOrTrailingWhitespace(line)); 
       outStr.Write(lineSep, 0, lineSep.Length); 
      } 
     } 
     else 
     { 
      // a single line file 
      if (lookAhead != -1) 
      { 
       byte[] line = lineOut.ToArray(); 
       outStr.Write(line, 0, GetLengthWithoutSeparatorOrTrailingWhitespace(line)); 
       outStr.Write(lineSep, 0, lineSep.Length); 
      } 
     } 
     outStr.Flush(); 
     //outStr.Close(); 


     PgpPublicKeyRingBundle pgpRings = new PgpPublicKeyRingBundle(keyIn); 

     PgpObjectFactory pgpFact = new PgpObjectFactory(aIn); 
     PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject(); 
     PgpSignature sig = p3[0]; 

     var key = pgpRings.GetPublicKey(sig.KeyId); 
     if (key == null) 
     { 
      throw new Exception("Can't verify the message signature."); 
     } 
     sig.InitVerify(key); 

     // 
     // read the input, making sure we ignore the last newline. 
     // 
     outStr.Seek(0, SeekOrigin.Begin); 
     StreamReader reader = new StreamReader(outStr); 
     string messageContent = reader.ReadToEnd(); 

     outStr.Seek(0, SeekOrigin.Begin); 

     Stream sigIn = outStr; //File.OpenRead(resultName); 

     lookAhead = ReadInputLine(lineOut, sigIn); 

     ProcessLine(sig, lineOut.ToArray()); 

     if (lookAhead != -1) 
     { 
      do 
      { 
       lookAhead = ReadInputLine(lineOut, lookAhead, sigIn); 

       sig.Update((byte)'\r'); 
       sig.Update((byte)'\n'); 

       ProcessLine(sig, lineOut.ToArray()); 
      } 
      while (lookAhead != -1); 
     } 

     sigIn.Close(); 

     if (sig.Verify()) { 
      // signature verified 
      return messageContent; 
     } else { 
      // signature verification failed 
      throw new Exception("Can't verify the message signature."); 
     } 
    } 


    private static int ReadInputLine(
      MemoryStream bOut, 
      Stream fIn) 
    { 
     bOut.SetLength(0); 

     int lookAhead = -1; 
     int ch; 

     while ((ch = fIn.ReadByte()) >= 0) 
     { 
      bOut.WriteByte((byte)ch); 
      if (ch == '\r' || ch == '\n') 
      { 
       lookAhead = ReadPassedEol(bOut, ch, fIn); 
       break; 
      } 
     } 

     return lookAhead; 
    } 

    private static int ReadPassedEol(
     MemoryStream bOut, 
     int lastCh, 
     Stream fIn) 
    { 
     int lookAhead = fIn.ReadByte(); 

     if (lastCh == '\r' && lookAhead == '\n') 
     { 
      bOut.WriteByte((byte)lookAhead); 
      lookAhead = fIn.ReadByte(); 
     } 

     return lookAhead; 
    } 

    private static void ProcessLine(
      PgpSignature sig, 
      byte[] line) 
    { 
     // note: trailing white space needs to be removed from the end of 
     // each line for signature calculation RFC 4880 Section 7.1 
     int length = GetLengthWithoutWhiteSpace(line); 
     if (length > 0) 
     { 
      sig.Update(line, 0, length); 
     } 
    } 

    private static void ProcessLine(
     Stream aOut, 
     PgpSignatureGenerator sGen, 
     byte[] line) 
    { 
     int length = GetLengthWithoutWhiteSpace(line); 
     if (length > 0) 
     { 
      sGen.Update(line, 0, length); 
     } 

     aOut.Write(line, 0, line.Length); 
    } 

    private static int GetLengthWithoutSeparatorOrTrailingWhitespace(byte[] line) 
    { 
     int end = line.Length - 1; 

     while (end >= 0 && IsWhiteSpace(line[end])) 
     { 
      end--; 
     } 

     return end + 1; 
    } 

    private static bool IsLineEnding(
     byte b) 
    { 
     return b == '\r' || b == '\n'; 
    } 

    private static int GetLengthWithoutWhiteSpace(
     byte[] line) 
    { 
     int end = line.Length - 1; 

     while (end >= 0 && IsWhiteSpace(line[end])) 
     { 
      end--; 
     } 

     return end + 1; 
    } 

    private static bool IsWhiteSpace(
     byte b) 
    { 
     return IsLineEnding(b) || b == '\t' || b == ' '; 
    } 

    private static int ReadInputLine(
     MemoryStream bOut, 
     int lookAhead, 
     Stream fIn) 
    { 
     bOut.SetLength(0); 

     int ch = lookAhead; 

     do 
     { 
      bOut.WriteByte((byte)ch); 
      if (ch == '\r' || ch == '\n') 
      { 
       lookAhead = ReadPassedEol(bOut, ch, fIn); 
       break; 
      } 
     } 
     while ((ch = fIn.ReadByte()) >= 0); 

     if (ch < 0) 
     { 
      lookAhead = -1; 
     } 

     return lookAhead; 
    } 

    private static byte[] LineSeparator 
    { 
     get { return Encoding.ASCII.GetBytes(Environment.NewLine); } 
    } 
関連する問題