List Info

Thread: Programming with GnuPG




Programming with GnuPG
user name
2006-01-24 22:58:00
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

jamieriell wrote:
> I imagine that the problem is there is another response
that needs to
> be made to the gpg process, however, i am unsure how to
do this.

Apologies for the long time in responding to this; life's
been busy
lately.

Try using the following stuff as a pattern.  However, be
warned, there
is no guarantee this stuff will actually compile.  There are
plenty of
places where I should be checking for exceptions but don't. 
Etcetera.
The purpose of this code is pedagogical, not production.

Also, before using any code supplied for you by anyone on
the 'net,
audit it first.  If you don't understand what it does, then
don't use it.

On with the show!



... You need to be careful how you get your path to GnuPG. 
On UNIX
platforms you can pretty safely assume it'll be in $PATH,
but on Windows
systems you'll need to search for a registry key. 
Fortunately, the code
to do this is pretty simple, and is best dropped in the ctor
of whatever
object you're writing to handle the GnuPG stuff.

===== in the ctor =====
if (128 == (int) System.Environment.OSVersion.Platform) {
  // we assume gpg is somewhere in $PATH
  _executable = "gpg";
  _flags = "--command-fd 0 --status-fd 2 --with-colons
";
} else {
  // we get gpg's location from the Windows registry
  // Please ignore the weird formatting here, such as
  // the "" + "SOFTWARE\GNU\GnuPG". 
It's broken up
  // in this way to help prevent wrapping in email,
  // _not_ because it needs to be this way in the code.
  Microsoft.Win32.RegistryKey rk =
Microsoft.Win32.Registry.LocalMachine.OpenSubKey(""
; +
"SOFTWARE\GNU\GnuPG");
  _executable = rk.GetValue("Install Directory") +
    "\gpg.exe";
  _flags = "--command-fd 0 --status-fd 2 --with-colons
";
}
===== end ctor stuff =====

protected Process StartNewGnuPGInstance(string cmdline)
{
  ProcessStartInfo psi = new ProcessStartInfo();
  psi.FileName = _executable;
  psi.Arguments = _flags + cmdline;
  psi.RedirectStandardOutput = true;
  psi.RedirectStandardInput = true;
  psi.RedirectStandardError = true;
  psi.UseShellExecute = false;
  Process p = Process.Start(psi);
  return p;
}


... Once you have StartNewGnuPGInstance, you can do most
simple
operations without any pain at all:

// In my code, an Interface.Key is an object corresponding
// to a GnuPG key.  You should be able to figure out its
// properties just from the code sample here.
public void setKeyEnabled(Interface.Key k, bool enabled)
{
  Process p = StartNewGnuPGInstance("--edit-key "
+
    k.Id);
  try {
    if (enabled)
      p.StandardInput.WriteLine("enable");
    else
      p.StandardInput.WriteLine("disable");
    p.StandardInput.WriteLine("save");
    p.Close();
  } catch (Exception exc) {
    // You need to be alert for exceptions here.
    // If there is _any_ set of conditions which
    // could cause GnuPG to abort or refuse to
    // start, then writing to your process could
    // potentially cause an exception.
  }
}


... Even more complicated stuff requiring you to read data
from GnuPG,
not just send data to it, is straightforward.  E.g.:

// CipherType is an enum mapping between GnuPG numeric
// values and names of various algorithms.
public CipherType[] GetKeyCipherPreferences(Interface.Key k)
{
  if (32 == k.Fingerprint.Length) {
    // Any key with a 128-bit fingerprint (32-char string)
    // is a legacy RSA key and can only use IDEA
    CipherType[] rv = { CipherType.CIPHER_IDEA }
    return rv;
  };

  Process p = StartNewGnuPGInstance("--edit-key "
+ k.Id);
  System.IO.TextReader output = p.StandardOutput;
  System.IO.TextWriter input = p.StandardInput;
  string line = output.ReadLine();
  // As soon as we hit a line beginning with
"uid", we know
  // we've got the key preferences--so just read through
  // what GnuPG gives us until we hit that line.
  while (true) {
    string[] colon_delims = line.Split(':');
    if ("uid" == colon_delims[0]) {
      string[] prefs = colon_delims[12].Split(' ');
      ArrayList al = new ArrayList();
      foreach (string pref in prefs)
        if ('S' == pref[0]) {
          string substr = pref.Substring(1);
          int comma = substr.IndexOf(',');
          if (-1 != comma)
            substr = substr.Substring(0, comma);
          al.Add(substr);
        }
      if (0 > al.IndexOf("2"))
        al.Add("2");
      CipherType[] rv = new CipherType[al.Count];
      for (int i = 0 ; i < al.Count ; i++)
        rv[i] = (CipherType)(Int32.Parse((String) al[i]));
      input.WriteLine("quit");
      p.Close();
      return rv;
    }
    line = output.ReadLine();
  }
}

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (Darwin)

iQEcBAEBCgAGBQJD1rD4AAoJELcA9IL+r4EJ3ikH/jkavS0pGvbCIcNa+juw
J5MM
Xx5M11F6bFnjHsXwwqWzpgmzhZXf9A/stVjDAldEl3RakhSXv1dvNFZTPGPY
7q47
ukEAXorWOeQaD1+GmrlhxrCxPwVnTOIs9UgLpxnrxAK7F57AhlZj458uLiU9
aj+y
nHvR7BzK2Wrh/VaBOS9xmZJilBaX3E5P4tDprj9oDlZU5aBl23oRhWdV2yVg
tSjJ
Cwx/woKTmSW33/Sik0MjnoN0lDPXUNJaEm122QX9XSPTaVuI+8MPoY61DHFY
MJVS
GiPq+DZsZXzvy8Sm8z9PYMASjj5R1kDzNeaUieXPVCOHx35HEnFn4hgN1KEg
f+Q=
=Aync
-----END PGP SIGNATURE-----


____________________________________________________________
__
Archives:         htt
p://groups.yahoo.com/group/PGP-Basics/messages
OT List:          http://gr
oups.yahoo.com/group/PGP-Basics-OT
OT Subscribe:    
mailto:PGP-Basics-OT-subscribe@yahoogroups.com 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://grou
ps.yahoo.com/group/PGP-Basics/

<*> To unsubscribe from this group, send an email to:
    PGP-Basics-unsubscribe@yahoogroups.com

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.c
om/info/terms/
 


Programming with GnuPG
user name
2006-01-27 17:56:44
--- In PGP-Basics@yahoogroups.com, "Robert J.
Hansen" <rjhs...> 
wrote:
>
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA512
> 
> jamieriell wrote:
> > I imagine that the problem is there is another
response that 
needs to
> > be made to the gpg process, however, i am unsure
how to do this.
> 
> Apologies for the long time in responding to this;
life's been busy
> lately.
> 
> Try using the following stuff as a pattern.  However,
be warned, 
there
> is no guarantee this stuff will actually compile. 
There are plenty 
of
> places where I should be checking for exceptions but
don't.  
Etcetera.
> The purpose of this code is pedagogical, not
production.
> 
> Also, before using any code supplied for you by anyone
on the 'net,
> audit it first.  If you don't understand what it does,
then don't 
use it.
> 
> On with the show!
> 
> 
> 
> ... You need to be careful how you get your path to
GnuPG.  On UNIX
> platforms you can pretty safely assume it'll be in
$PATH, but on 
Windows
> systems you'll need to search for a registry key. 
Fortunately, the 
code
> to do this is pretty simple, and is best dropped in the
ctor of 
whatever
> object you're writing to handle the GnuPG stuff.
> 
> ===== in the ctor =====
> if (128 == (int) System.Environment.OSVersion.Platform)
{
>   // we assume gpg is somewhere in $PATH
>   _executable = "gpg";
>   _flags = "--command-fd 0 --status-fd 2
--with-colons ";
> } else {
>   // we get gpg's location from the Windows registry
>   // Please ignore the weird formatting here, such as
>   // the "" +
"SOFTWARE\GNU\GnuPG".  It's broken up
>   // in this way to help prevent wrapping in email,
>   // _not_ because it needs to be this way in the code.
>   Microsoft.Win32.RegistryKey rk =
>
Microsoft.Win32.Registry.LocalMachine.OpenSubKey(""
; +
> "SOFTWARE\GNU\GnuPG");
>   _executable = rk.GetValue("Install
Directory") +
>     "\gpg.exe";
>   _flags = "--command-fd 0 --status-fd 2
--with-colons ";
> }
> ===== end ctor stuff =====
> 
> protected Process StartNewGnuPGInstance(string cmdline)
> {
>   ProcessStartInfo psi = new ProcessStartInfo();
>   psi.FileName = _executable;
>   psi.Arguments = _flags + cmdline;
>   psi.RedirectStandardOutput = true;
>   psi.RedirectStandardInput = true;
>   psi.RedirectStandardError = true;
>   psi.UseShellExecute = false;
>   Process p = Process.Start(psi);
>   return p;
> }
> 
> 
> ... Once you have StartNewGnuPGInstance, you can do
most simple
> operations without any pain at all:
> 
> // In my code, an Interface.Key is an object
corresponding
> // to a GnuPG key.  You should be able to figure out
its
> // properties just from the code sample here.
> public void setKeyEnabled(Interface.Key k, bool
enabled)
> {
>   Process p = StartNewGnuPGInstance("--edit-key
" +
>     k.Id);
>   try {
>     if (enabled)
>       p.StandardInput.WriteLine("enable");
>     else
>       p.StandardInput.WriteLine("disable");
>     p.StandardInput.WriteLine("save");
>     p.Close();
>   } catch (Exception exc) {
>     // You need to be alert for exceptions here.
>     // If there is _any_ set of conditions which
>     // could cause GnuPG to abort or refuse to
>     // start, then writing to your process could
>     // potentially cause an exception.
>   }
> }
> 
> 
> ... Even more complicated stuff requiring you to read
data from 
GnuPG,
> not just send data to it, is straightforward.  E.g.:
> 
> // CipherType is an enum mapping between GnuPG numeric
> // values and names of various algorithms.
> public CipherType[]
GetKeyCipherPreferences(Interface.Key k)
> {
>   if (32 == k.Fingerprint.Length) {
>     // Any key with a 128-bit fingerprint (32-char
string)
>     // is a legacy RSA key and can only use IDEA
>     CipherType[] rv = { CipherType.CIPHER_IDEA }
>     return rv;
>   };
> 
>   Process p = StartNewGnuPGInstance("--edit-key
" + k.Id);
>   System.IO.TextReader output = p.StandardOutput;
>   System.IO.TextWriter input = p.StandardInput;
>   string line = output.ReadLine();
>   // As soon as we hit a line beginning with
"uid", we know
>   // we've got the key preferences--so just read
through
>   // what GnuPG gives us until we hit that line.
>   while (true) {
>     string[] colon_delims = line.Split(':');
>     if ("uid" == colon_delims[0]) {
>       string[] prefs = colon_delims[12].Split(' ');
>       ArrayList al = new ArrayList();
>       foreach (string pref in prefs)
>         if ('S' == pref[0]) {
>           string substr = pref.Substring(1);
>           int comma = substr.IndexOf(',');
>           if (-1 != comma)
>             substr = substr.Substring(0, comma);
>           al.Add(substr);
>         }
>       if (0 > al.IndexOf("2"))
>         al.Add("2");
>       CipherType[] rv = new CipherType[al.Count];
>       for (int i = 0 ; i < al.Count ; i++)
>         rv[i] = (CipherType)(Int32.Parse((String)
al[i]));
>       input.WriteLine("quit");
>       p.Close();
>       return rv;
>     }
>     line = output.ReadLine();
>   }
> }
> 
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.2 (Darwin)
> 
>
iQEcBAEBCgAGBQJD1rD4AAoJELcA9IL+r4EJ3ikH/jkavS0pGvbCIcNa+juw
J5MM
>
Xx5M11F6bFnjHsXwwqWzpgmzhZXf9A/stVjDAldEl3RakhSXv1dvNFZTPGPY
7q47
>
ukEAXorWOeQaD1+GmrlhxrCxPwVnTOIs9UgLpxnrxAK7F57AhlZj458uLiU9
aj+y
>
nHvR7BzK2Wrh/VaBOS9xmZJilBaX3E5P4tDprj9oDlZU5aBl23oRhWdV2yVg
tSjJ
>
Cwx/woKTmSW33/Sik0MjnoN0lDPXUNJaEm122QX9XSPTaVuI+8MPoY61DHFY
MJVS
>
GiPq+DZsZXzvy8Sm8z9PYMASjj5R1kDzNeaUieXPVCOHx35HEnFn4hgN1KEg
f+Q=
> =Aync
> -----END PGP SIGNATURE-----
>
Thank you very much for the response, it was very helpful. I
am stuck 
at the final point of encryption where it would normally
prompt 
to "end with an empty line". I have the code
doing: 
p.StandardInput.WriteLine(""); in hope that this
would represent the 
empty line. The application seems to not perform the
encyption, 
however, when I do this.

Any ideas on that would be helpfull. Also, I am having
trouble using 
p.StandardOutput.ReadLine(); It seems to hang the
application when 
this occurs.

Thanks for the help.






____________________________________________________________
__
Archives:         htt
p://groups.yahoo.com/group/PGP-Basics/messages
OT List:          http://gr
oups.yahoo.com/group/PGP-Basics-OT
OT Subscribe:    
mailto:PGP-Basics-OT-subscribe@yahoogroups.com 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://grou
ps.yahoo.com/group/PGP-Basics/

<*> To unsubscribe from this group, send an email to:
    PGP-Basics-unsubscribe@yahoogroups.com

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.c
om/info/terms/
 


[1-2]

about | contact  Other archives ( Real Estate discussion Medical topics )