static void Main() { // Create GPGME context Context ctx = new Context(); // Open a PGP public key from file "daniel.pub" GpgmeFileData keyfile = new GpgmeFileData(@"daniel.pub"); // Import the PGP key KeyStore store = ctx.KeyStore; ImportResult rst = store.Import(keyfile); // Show the results Console.WriteLine("Keys imported {0}\n" + "Keys skipped: {1}\n" + "Keys unchanged: {2}\n" + "Keys not imported: {3}\n", rst.Imported, rst.SkippedNewKeys, rst.Unchanged, rst.NotImported); if (rst.Imports != null) { Console.WriteLine("Found keys: "); foreach (ImportStatus status in rst.Imports) { Console.WriteLine("Key fingerprint: {0}\n", status.Fpr); } } }
public FileManager(string _sKey, string _sEmailCadastradoNaChave) { this.sKey = _sKey; this.sEmailCadastradoNaChave = _sEmailCadastradoNaChave; GpgmeFileData keyfile = new GpgmeFileData(sKey); keyStore = ctx.KeyStore; ImportResult rst = keyStore.Import(keyfile); keyring = ctx.KeyStore; keys = keyring.GetKeyList(sEmailCadastradoNaChave, false); keyfile.Close(); }
/// <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); } } }
/// <summary> /// Imports the public GPG keys into the local GPG home directory /// </summary> /// <param name="keys">Keys to import</param> /// <param name="tempCtx">Temporary GPGME context</param> private void ImportPublicGpgKeys(IEnumerable <Key> keys, Context tempCtx) { foreach (var key in keys) { var tempFile = Path.GetTempFileName(); try { // Export public key from temporary keychain and import into real keychain tempCtx.KeyStore.Export(key.KeyId, tempFile); using (var tempFileData = new GpgmeFileData(tempFile)) { _ctx.KeyStore.Import(tempFileData); } } finally { File.Delete(tempFile); } } }
/// <summary> /// Adds a new key to the secret storage. /// </summary> /// <param name="inputPath"></param> public void AddKey(string inputPath) { // Create a temporary directory to hold the GPG key while we verify that it's legit var tempHomedir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Console.WriteLine($"Using {tempHomedir} as temp directory."); Directory.CreateDirectory(tempHomedir); try { using (var tempCtx = new Context()) { tempCtx.SetEngineInfo(Protocol.OpenPGP, null, tempHomedir); tempCtx.PinentryMode = PinentryMode.Error; ImportResult result; using (var keyfile = new GpgmeFileData(inputPath)) { result = tempCtx.KeyStore.Import(keyfile); } if (result == null || result.Imported == 0 || result.SecretImported == 0 || result.Imports == null) { throw new Exception("No secret keys found!"); } var fingerprints = result.Imports.Where(x => x.NewSecretKey).Select(x => x.Fpr); Console.WriteLine($"Found fingerprints: {string.Join(", ", fingerprints)}"); var keys = GetAndVerifyKeys(fingerprints, tempCtx); EnsureGpgKeysDoNotExist(keys); Console.WriteLine(); ImportAndEncryptSecretGpgKeys(keys, tempHomedir); ImportPublicGpgKeys(keys, tempCtx); } } finally { Directory.Delete(tempHomedir, true); } }
/// <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 Stream Sign(Stream 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(); var outputPath = Path.GetTempFileName(); _filesToDelete.Add(outputPath); try { File.WriteAllBytes(keygripPath, secretKeyFile); input.CopyToFile(inputPath); 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 GpgmeFileData(outputPath, FileMode.Create, FileAccess.Write)) { var result = _ctx.Sign(inputData, sigData, SignatureMode.Detach); if (result.InvalidSigners != null) { throw new Exception($"Could not sign: {result.InvalidSigners.Reason}"); } } return(File.OpenRead(outputPath)); } finally { File.Delete(keygripPath); File.Delete(inputPath); } } }
public void Encrypt() { PgpKey pKey = (PgpKey)keys[0]; UTF8Encoding utf8 = new UTF8Encoding(); string secrettext = System.IO.File.ReadAllText(Source); plain.FileName = Source; BinaryWriter binwriter = new BinaryWriter(plain, utf8); binwriter.Write(secrettext.ToCharArray()); binwriter.Flush(); binwriter.Seek(0, SeekOrigin.Begin); ctx.Armor = true; GpgmeData cipher = new GpgmeFileData(Destination, FileMode.Create, FileAccess.ReadWrite); cipher.FileName = Destination; var result = ctx.Encrypt(new Key[] { pKey }, EncryptFlags.AlwaysTrust, plain, cipher); cipher.Close(); }
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); } } }
static void Main() { Context ctx = new Context(); if (ctx.Protocol != Protocol.OpenPGP) { ctx.SetEngineInfo(Protocol.OpenPGP, null, null); } Console.WriteLine("Search Alice's PGP key in the default keyring.."); const string SEARCHSTR = "*****@*****.**"; IKeyStore keyring = ctx.KeyStore; // retrieve all keys that have Alice's email address Key[] keys = keyring.GetKeyList(SEARCHSTR, false); if (keys == null || keys.Length == 0) { Console.WriteLine("Cannot find Alice'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 alice = (PgpKey)keys[0]; if (alice.Uid == null || alice.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 origintxt = new string('+', 508) + " Die Gedanken sind frei " + new string('+', 508) + randomtext; Console.WriteLine("Text to be signed:\n\n{0}", origintxt); // we want our string UTF8 encoded. UTF8Encoding utf8 = new UTF8Encoding(); // Prepare a file for later usage File.WriteAllText("original.txt", origintxt, utf8); /////// SIGN DATA (detached signature) /////// Console.Write("Write a detached signature to file: original.txt.sig.. "); GpgmeData origin = new GpgmeFileData("original.txt", FileMode.Open, FileAccess.Read); GpgmeData detachsig = new GpgmeFileData("original.txt.sig", FileMode.Create, FileAccess.Write); // Set Alice as signer ctx.Signers.Clear(); ctx.Signers.Add(alice); // 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); // create a detached signature SignatureResult sigrst = ctx.Sign( origin, // plain text (source buffer) detachsig, // signature (destination buffer) SignatureMode.Detach); Console.WriteLine("done."); // print out invalid signature keys if (sigrst.InvalidSigners != null) { foreach (InvalidKey key in sigrst.InvalidSigners) { Console.WriteLine("Invalid key: {0} ({1})", key.Fingerprint, key.Reason); } } // print out signature information if (sigrst.Signatures != null) { foreach (NewSignature newsig in sigrst.Signatures) { Console.WriteLine("New signature: " + "\n\tFingerprint: {0}" + "\n\tHash algorithm: {1}" + "\n\tKey algorithm: {2}" + "\n\tTimestamp: {3}" + "\n\tType: {4}", newsig.Fingerprint, Gpgme.GetHashAlgoName(newsig.HashAlgorithm), Gpgme.GetPubkeyAlgoName(newsig.PubkeyAlgorithm), newsig.Timestamp, newsig.Type); } } origin.Close(); detachsig.Close(); /////// VERIFY DATA (detached signature) /////// Console.Write("Verify a detached signature from file: original.txt.sig.. "); origin = new GpgmeFileData("original.txt", FileMode.Open, FileAccess.Read); detachsig = new GpgmeFileData("original.txt.sig", FileMode.Open, FileAccess.Read); VerificationResult verrst = ctx.Verify( detachsig, // detached signature origin, // original data null); // should be NULL if a detached signature has been provided Console.WriteLine("done."); Console.WriteLine("Filename: {0}", verrst.FileName); // print out signature information 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); } } }