public static void Main(string[] args) { // Create some sample data byte[] bytedata = new byte[1024]; for (int i = 0; i < bytedata.Length; i++) { bytedata[i] = (byte)(i % 256); } // Create memory based buffer for GPGME GpgmeMemoryData memdata = new GpgmeMemoryData(); // write sample data into the GPGME memory based buffer Console.WriteLine("Bytes written: " + memdata.Write(bytedata, bytedata.Length)); // Set the cursor to the beginning Console.WriteLine("Seek to begin: " + memdata.Seek(0, SeekOrigin.Begin)); // Re-read the data into a tempory buffer byte[] tmp = new byte[bytedata.Length]; Console.WriteLine("Bytes read: " + memdata.Read(tmp)); // Create stream based buffer (CBS) MemoryStream memstream = new MemoryStream(tmp); GpgmeStreamData streamdata = new GpgmeStreamData(memstream); // .. Console.WriteLine("Bytes written: " + streamdata.Write(bytedata, bytedata.Length)); Console.WriteLine("Seek to begin: " + streamdata.Seek(0, SeekOrigin.Begin)); byte[] tmp2 = new byte[bytedata.Length]; Console.WriteLine("Bytes read: " + streamdata.Read(tmp2)); }
/// <summary> /// Gets all the keys with the specified fingerprints, and verifies that they can be used for signing /// </summary> /// <param name="fingerprints">Fingerprints of the keys</param> /// <param name="ctx">GPGME context to use</param> /// <returns>List of all the keys</returns> private static List <Key> GetAndVerifyKeys(IEnumerable <string> fingerprints, Context ctx) { // Ensure all keys work by signing a message with them var original = new GpgmeMemoryData { FileName = "original.txt" }; var writer = new BinaryWriter(original, Encoding.UTF8); writer.Write("Hello World!"); var keys = new List <Key>(); foreach (var fingerprint in fingerprints) { var output = new GpgmeMemoryData { FileName = "original.txt.gpg" }; var key = ctx.KeyStore.GetKey(fingerprint, true); ctx.Signers.Clear(); ctx.Signers.Add(key); try { var signResult = ctx.Sign(original, output, SignatureMode.Detach); if (signResult.InvalidSigners != null) { var firstInvalidKey = signResult.InvalidSigners.First(); throw new Exception( $"Invalid signer: {firstInvalidKey.Fingerprint} ({firstInvalidKey.Reason})" ); } keys.Add(key); } catch (GpgmeException ex) { // TODO: Expose GPG error code through gpgme-sharp, to avoid string comparison if (ex.Message.Contains("NO_PIN_ENTRY")) { throw new Exception( "SecureSign does not support passphrase-protected GPG keys. " + "Please export your key without a passphrase." ); } throw; } } return(keys); }
/// <summary> /// Signs the specified artifact using GPG /// </summary> /// <param name="input">Bytes to sign</param> /// <param name="keygrip">Hex representation of keygrip</param> /// <param name="secretKeyFile">Contents of the secret key file</param> /// <param name="fingerprint">Fingerprint of the key</param> /// <returns>ASCII-armored signature</returns> public byte[] Sign(byte[] input, string keygrip, byte[] secretKeyFile, string fingerprint) { // Since this signer messes with some global state (private keys in the GPG home directory), // we must lock to ensure no other signing requests happen concurrently. lock (_signLock) { var keygripPath = Path.Combine(_pathConfig.GpgHome, "private-keys-v1.d", keygrip + ".key"); var inputPath = Path.GetTempFileName(); try { File.WriteAllBytes(keygripPath, secretKeyFile); File.WriteAllBytes(inputPath, input); var key = _ctx.KeyStore.GetKey(fingerprint, secretOnly: true); _ctx.Signers.Clear(); _ctx.Signers.Add(key); _ctx.Armor = true; using (var inputData = new GpgmeFileData(inputPath, FileMode.Open, FileAccess.Read)) using (var sigData = new GpgmeMemoryData { FileName = "signature.asc" }) { var result = _ctx.Sign(inputData, sigData, SignatureMode.Detach); if (result.InvalidSigners != null) { throw new Exception($"Could not sign: {result.InvalidSigners.Reason}"); } using (var memStream = new MemoryStream()) { sigData.Seek(0, SeekOrigin.Begin); sigData.CopyTo(memStream); return(memStream.GetBuffer()); } } } finally { File.Delete(keygripPath); File.Delete(inputPath); } } }
static void Main(string[] args) { Context ctx = new Context(); if (ctx.Protocol != Protocol.OpenPGP) { ctx.SetEngineInfo(Protocol.OpenPGP, null, null); } Console.WriteLine("Search Bob's PGP key in the default keyring.."); String searchstr = "*****@*****.**"; IKeyStore keyring = ctx.KeyStore; // retrieve all keys that have Bob's email address Key[] keys = keyring.GetKeyList(searchstr, false); if (keys == null || keys.Length == 0) { Console.WriteLine("Cannot find Bob's PGP key {0} in your keyring.", searchstr); Console.WriteLine("You may want to create the PGP key by using the appropriate\n" + "sample in the Samples/ directory."); return; } // print a list of all returned keys foreach (Key key in keys) { if (key.Uid != null && key.Fingerprint != null) { Console.WriteLine("Found key {0} with fingerprint {1}", key.Uid.Name, key.Fingerprint); } } // we are going to use the first key in the list PgpKey bob = (PgpKey)keys[0]; if (bob.Uid == null || bob.Fingerprint == null) { throw new InvalidKeyException(); } // Create a sample string StringBuilder randomtext = new StringBuilder(); for (int i = 0; i < 80 * 6; i++) { randomtext.Append((char)(34 + i % 221)); } string secrettext = new string('+', 508) + " Die Gedanken sind frei " + new string('+', 508) + randomtext.ToString(); Console.WriteLine("Text to be encrypted:\n\n{0}", secrettext); // we want our string UTF8 encoded. UTF8Encoding utf8 = new UTF8Encoding(); // create a (dynamic) memory based data buffer to place the unencrypted (plain) text GpgmeData plain = new GpgmeMemoryData(); // set a filename for this data buffer plain.FileName = "my_document.txt"; BinaryWriter binwriter = new BinaryWriter(plain, utf8); // write our secret text to the memory buffer binwriter.Write(secrettext.ToCharArray()); binwriter.Flush(); // go to the beginning(!) binwriter.Seek(0, SeekOrigin.Begin); /////// ENCRYPT DATA /////// // we want or PGP encrypted data RADIX/BASE64 encoded. ctx.Armor = true; // create another (dynamic) memory based data buffer as destination GpgmeData cipher = new GpgmeMemoryData(); cipher.FileName = "my_document.txt"; Console.Write("Encrypt data for {0} ({1}).. ", bob.Uid.Name, bob.KeyId); EncryptionResult encrst = ctx.Encrypt( new Key[] { bob }, // encrypt data to Bob's key only EncryptFlags.AlwaysTrust, // trust our sample PGP key plain, // source buffer cipher); // destination buffer Console.WriteLine("done."); Console.WriteLine("Cipher text:"); // move cursor to the beginning cipher.Seek(0, SeekOrigin.Begin); /* Read cipher text from libgpgme's memory based buffer and print * it to the console screen. */ char[] buf; // the cipher text is UTF8 encoded BinaryReader binreader = new BinaryReader(cipher, utf8); while (true) { try { buf = binreader.ReadChars(255); if (buf.Length == 0) { break; } Console.Write(buf); } catch (EndOfStreamException) { break; } } /////// DECRYPT DATA /////// /* Set the password callback - needed if the user doesn't run * gpg-agent or any other password / pin-entry software. */ ctx.SetPassphraseFunction(new PassphraseDelegate(MyPassphraseCallback)); // go to the beginning(!) cipher.Seek(0, SeekOrigin.Begin); Console.Write("Decrypt data.. "); GpgmeData decryptedText = new GpgmeMemoryData(); DecryptionResult decrst = ctx.Decrypt( cipher, // source buffer decryptedText); // destination buffer Console.WriteLine("Done. Filename: \"{0}\" Recipients:", decrst.FileName); /* print out all recipients key ids (a PGP package can be * encrypted to various recipients). */ if (decrst.Recipients != null) { foreach (Recipient recp in decrst.Recipients) { Console.WriteLine("\tKey id {0} with {1} algorithm", recp.KeyId, Gpgme.GetPubkeyAlgoName(recp.KeyAlgorithm)); } } else { Console.WriteLine("\tNone"); } // TEST: Compare original data and decrypted data byte[] orig = new byte[255], cmp = new byte[255]; plain.Seek(0, SeekOrigin.Begin); decryptedText.Seek(0, SeekOrigin.Begin); while (true) { try { int a, b; a = plain.Read(orig, orig.Length); b = decryptedText.Read(cmp, cmp.Length); if (a != b) { throw new DecryptionFailedException("The two data buffers have different sizes."); } if (a == 0) { break; // everything okay - end of stream reached. } for (int i = 0; i < a; i++) { if (orig[i] != cmp[i]) { throw new DecryptionFailedException("The two data buffers differ at position " + i.ToString() + "."); } } } catch (EndOfStreamException) { throw new DecryptionFailedException("The two data buffers have different sizes."); } } // we do not want our GpgmeData buffers destroyed GC.KeepAlive(binwriter); GC.KeepAlive(binreader); /////// FILE BASED DATA BUFFERS /////// /////// ENCRYPT FILE /////// // Now let's use a file based data buffers // create the "source" file first and fill it with our sample text. Console.WriteLine("Create new file plainfile.txt."); File.WriteAllText("plainfile.txt", secrettext, utf8); GpgmeData plainfile = new GpgmeFileData( "plainfile.txt", FileMode.Open, FileAccess.Read); GpgmeData cipherfile = new GpgmeFileData( "cipherfile.asc", FileMode.Create, FileAccess.ReadWrite); Console.Write("Encrypt file plainfile.txt to cipherfile.asc.. "); encrst = ctx.Encrypt( new Key[] { bob }, EncryptFlags.AlwaysTrust, plainfile, cipherfile); Console.WriteLine("done."); plainfile.Close(); cipherfile.Close(); /////// DECRYPT FILE /////// //cipherfile = new GpgmeFileData("cipherfile.asc"); // load the file content into the system memory cipherfile = new GpgmeMemoryData("cipherfile.asc"); plainfile = new GpgmeFileData( "decrypted.txt", FileMode.Create, FileAccess.Write); Console.WriteLine("Decrypt file cipherfile.asc to decrypted.txt.. "); decrst = ctx.Decrypt( cipherfile, // source buffer plainfile); // destination buffer Console.WriteLine("Done. Filename: \"{0}\" Recipients:", decrst.FileName); /* print out all recipients key ids (a PGP package can be * encrypted to various recipients). */ if (decrst.Recipients != null) { foreach (Recipient recp in decrst.Recipients) { Console.WriteLine("\tKey id {0} with {1} algorithm", recp.KeyId, Gpgme.GetPubkeyAlgoName(recp.KeyAlgorithm)); } } else { Console.WriteLine("\tNone"); } cipherfile.Close(); plainfile.Close(); return; }
static void Main() { Context ctx = new Context(); if (ctx.Protocol != Protocol.OpenPGP) { ctx.SetEngineInfo(Protocol.OpenPGP, null, null); } Console.WriteLine("Search Bob's and Alice's PGP keys in the default keyring.."); String[] searchpattern = new[] { "*****@*****.**", "*****@*****.**" }; IKeyStore keyring = ctx.KeyStore; // We want the key signatures! ctx.KeylistMode = KeylistMode.Signatures; // retrieve all keys that have Bob's or Alice's email address Key[] keys = keyring.GetKeyList(searchpattern, false); PgpKey bob = null, alice = null; if (keys != null && keys.Length != 0) { foreach (Key k in keys) { if (k.Uid != null) { if (bob == null && k.Uid.Email.ToLower().Equals("*****@*****.**")) { bob = (PgpKey)k; } if (alice == null && k.Uid.Email.ToLower().Equals("*****@*****.**")) { alice = (PgpKey)k; } } else { throw new InvalidKeyException(); } } } if (bob == null || alice == null) { Console.WriteLine("Cannot find Bob's or Alice's PGP key in your keyring."); Console.WriteLine("You may want to create the PGP keys by using the appropriate\n" + "sample in the Samples/ directory."); return; } // Create a sample string StringBuilder randomtext = new StringBuilder(); for (int i = 0; i < 80 * 6; i++) { randomtext.Append((char)(34 + i % 221)); } string origintxt = new string('+', 508) + " Die Gedanken sind frei " + new string('+', 508) + randomtext; // we want our string UTF8 encoded. UTF8Encoding utf8 = new UTF8Encoding(); // Write sample string to plain.txt File.WriteAllText("plain.txt", origintxt, utf8); /////// ENCRYPT AND SIGN DATA /////// Console.Write("Encrypt data for Bob and sign it with Alice's PGP key.. "); GpgmeData plain = new GpgmeFileData("plain.txt"); GpgmeData cipher = new GpgmeFileData("cipher.asc"); // we want or PGP encrypted/signed data RADIX/BASE64 encoded. ctx.Armor = true; /* Set the password callback - needed if the user doesn't run * gpg-agent or any other password / pin-entry software. */ ctx.SetPassphraseFunction(MyPassphraseCallback); // Set Alice's PGP key as signer ctx.Signers.Clear(); ctx.Signers.Add(alice); EncryptionResult encrst = ctx.EncryptAndSign( new Key[] { bob }, EncryptFlags.AlwaysTrust, plain, cipher); Console.WriteLine("done."); // print out invalid signature keys if (encrst.InvalidRecipients != null) { foreach (InvalidKey key in encrst.InvalidRecipients) { Console.WriteLine("Invalid key: {0} ({1})", key.Fingerprint, key.Reason); } } plain.Close(); cipher.Close(); /////// DECRYPT AND VERIFY DATA /////// Console.Write("Decrypt and verify data.. "); cipher = new GpgmeFileData("cipher.asc"); plain = new GpgmeMemoryData(); CombinedResult comrst = ctx.DecryptAndVerify( cipher, // source buffer plain); // destination buffer Console.WriteLine("Done. Filename: \"{0}\" Recipients:", comrst.DecryptionResult.FileName); /* print out all recipients key ids (a PGP package can be * encrypted to various recipients). */ DecryptionResult decrst = comrst.DecryptionResult; if (decrst.Recipients != null) { foreach (Recipient recp in decrst.Recipients) { Console.WriteLine("\tKey id {0} with {1} algorithm", recp.KeyId, Gpgme.GetPubkeyAlgoName(recp.KeyAlgorithm)); } } else { Console.WriteLine("\tNone"); } // print out signature information VerificationResult verrst = comrst.VerificationResult; if (verrst.Signature != null) { foreach (Signature sig in verrst.Signature) { Console.WriteLine("Verification result (signature): " + "\n\tFingerprint: {0}" + "\n\tHash algorithm: {1}" + "\n\tKey algorithm: {2}" + "\n\tTimestamp: {3}" + "\n\tSummary: {4}" + "\n\tValidity: {5}", sig.Fingerprint, Gpgme.GetHashAlgoName(sig.HashAlgorithm), Gpgme.GetPubkeyAlgoName(sig.PubkeyAlgorithm), sig.Timestamp, sig.Summary, sig.Validity); } } }