TOC 
M. Rose
 Dover Beach Consulting, Inc.
 September 25, 2002

Tcl GPGME v1.0.1

Abstract

Tcl GPGME provides a Tcl interface to the GnuGPG Made Easy library.



 TOC 

Table of Contents




 TOC 

1. SYNOPSIS

    package provide gpgme 1.0

Tcl GPGME provides a Tcl interface to the GnuPG Made Easy library.

This document won't tell you what GPG[1] is. What it will tell you, the Tcl programmer, is how you can access the GPGME library from your Tcl script.

1.1 Requirements

First, you'll need to have GPGME v0.3.11 (or later) already installed. Look in the download area.

GPGME requires GPG v1.0.7 (or later). Look in the download area.

Note that if you're upgrading to v1.0.7, then there's a disasterous little gotcha that will prevent programs like "Gabber" from working with GPG. Here's the diff you want to apply before compiling:

--- gnupg-1.0.7/g10/_g10.c      Thu Apr 25 00:57:21 2002
+++ gnupg-1.0.7/g10/g10.c       Wed Aug 28 13:12:49 2002
@@ -860,7 +860,9 @@
         opt.homedir = buf;
     }
 #endif
+#if 0
 #undef USE_SHM_COPROCESSING     /* huh? */
+#endif
 #ifdef USE_SHM_COPROCESSING
     if( opt.shm_coprocess ) {
        init_shm_coprocessing(requested_shm_size, 1 );

(Note that patch has no impact on GPGME, so if you want to use Tcl GPGME, but you're uncomfortable recompiling GPG, you don't need to install this patch.)

Finally, if for some reason you have this documentation, but not the source distribution of Tcl GPGME, you can find it here.

1.2 Limitations

Although GPGME is described as "alpha" code and has an embyronic version number, it's surprisingly well-featured and stable.

Tcl GPGME implements most of GPGME with two exceptions:

As soon as I have a need for them, I'll implement them. Of course, this is all open source, so what's stopping you from doing the work?



 TOC 

2. CONVENTIONS

2.1 Return Codes

If an exception occurs in a GPGME library function, an error is thrown and the errorCode global is set to a list containing four elements:

2.2 Data Types

A serialized array is a list that contains an series of keywords and values.

A serialized array can be traversed using foreach, e.g.,

    foreach {k v} $aList {
        puts stdout "$k has value $v"
    }

Alternatively, an array can be initialized and accessed, e.g.,

    array set data $aList
    if {[info exists data(plugin)]} {
        puts stdout "plugin entry is present"
    }

When Tcl GPGME returns a serialized array, a few properties, if present, are worth noting:

key:
contains a key token.
signatures:
contains a list of serialized arrays, each corresponding to a signature; in turn, each signature is a serialized array of properties.
subkeys:
contains a list of serialized arrays, one for each subkey present in a key.
xml:
a string containing an XML document describing a key or signature.

2.3 Callbacks

Callbacks are invoked with a single argument, a serialized array.

The passphrase callback returns a string. The serialized array contains these elements:

token:
a context token
description:
a string containing three lines:
  • the string "ENTER" or "TRY_AGAIN";
  • a userid "hint", consisting of the keyid for the (sub)key of interest, a space, and then the userid; and,
  • passphrase information, consisting of four space-separated tokens: the keyid of the (sub)key of interest, the keyid of the corresponding mainkey, the algorithm number (e.g., DSA is 17), and the number 0.

(In case you're wondering, this format isn't part of the documented PGPME interface — they'd be passed as individual elements in the serialized array.)



 TOC 

3. PROCEDURES

3.1 Context Management

gpgme::new

Return a "context token". To destroy it, rename it to the empty string.

$token -operation cancel

Cancel any pending operation for the context, e.g., a passphrase retrieval.

$token -operation wait \
      ?-blocking boolean?

Wait for any pending operation to complete, optionally blocking. (Note that since the current version of Tcl GPGME doesn't support asynchronous operations, this is presently a no-op, as are the progress and idle callbacks.)

$token -operation get \
      ?-property  string?

Return a string corresponding to the value of the given -property. If no property is specified, a list of readable properties is returned.

$token -operation set     \
      ?-property  string? \
      ?-value     string?

Set the -value of the given -property, and return the empty-string. If no property is specified, a list of writable properties is returned.

The syntax of some of these properties is worth mentioning:

protocol:
cf., gpgme::info protocols to see what choices are available
armor/textmode:
boolean
keylistmode:
a list of values, cf., gpgme::info keylist-modes to see what values are available
passphrase-callback:
a script, obviously
signers:
a list of key tokens

$token -operation info

Return a list of operations for the context token.

3.2 Functions to handle recipients

gpgme::recipient

Return a "recipients token". To destroy it, rename it to the empty string.

$token -operation add    \
       -name      string \
      ?-validity valid?

Add a name to the recipient set. The -validity switch indicates the minimum acceptable validity (cf., gpgme::info validity to see what choices are available).

$token -operation count

Return the number of names in the recipient set.

$token -operation list

Return a list of the names in the recipient set.

$token -operation info

Return a list of operations for the recipient token.

3.3 Key and trust functions

$token -operation  start-key \
      ?-pattern    list?     \
      ?-secretonly boolean?

Start examining the context for keys that match any of the given patterns. Optionally, look for only those keys for which a secret key is available.

$token -operation next-key

Return a key token matching the given pattern.

$token -operation done-key

Cancel the search in progress.

$token -operation info-key

Return a serialized array of properties for the key token.

$token -operation start-trustitem \
       -pattern   string          \
      ?-maxlevel  integer?

Start examining the context for trust items that match the given pattern.

$token -operation next-trustitem

Return an item token matching the given pattern.

$token -operation done-trustitem

Cancel the search in progress.

$token -operation info-trustitem

Return a serialized array of properties for the item token.

3.4 Crypto operation functions

$token -operation  encrypt \
       -input      string  \
       -recipients token   \
      ?-sign       boolean?

Encipher the given string for the indicated recipients, optionally signing it, and return a binary string containing the result.

$token -operation   decrypt \
       -input       string  \
      ?-checkstatus boolean?

Decipher the given string, optionally checking its signature validity, and return a serialized array. At a minimum, the serialized array has a plaintext property containing a binary string; it may also have a status property, describing the validity of the signature (cf., gpgme::info signature-status).

$token -operation sign   \
       -input     string \
      ?-mode      mode?

Return a signature for the given string, (cf., gpgme::info signature-modes for the possible signature modes).

$token -operation verify
       -signature string \
      ?-input     string?

Check a signature's validity and return a serialized array. (If an input string is not present, then the signature's mode is either normal or cleartext; otherwise the mode is detached.) At a minimum, the serialized array has a status property describing the validity of the signature (cf., gpgme::info signature-status), and a signatures property; it may also have a plaintext property containing a binary string.

3.5 Miscellaneous calls

gpgme::check_version string

Verify that the GPGME library is at least as current as the indicated version, raise an error if not.

gpgme::get_engine_info

Return an XML document describing the configuration of the current protocol engine.

gpgme::engine_check_version protocol

Verify that the indicated protocol engine is propertly configured, raise an error if not.



 TOC 

4. EXAMPLE

package require gpgme



# get a passphrase from the user

proc passphrase {data} {
    global passphrases

    array set params $data

# break down the three lines...
    set lines [split [string trimright $params(description)] "\n"]
    set text [lindex $lines 0]
    if {[set x [string first " " [set keyid [lindex $lines 1]]]] > 0} {
        set userid [string range $keyid [expr $x+1] end]
        set keyid [string range $keyid 0 [expr $x-1]]
    } else {
        set userid unknown!
    }

# see if we can use a cached value...
    if {([cequal $text ENTER]) \
            &&([info exists passphrases($keyid)]) \
            && (![cequal $passphrases($keyid) ""])} {
        return $passphrases($keyid)
    }

    set title "Please enter passphrase"
    switch -- $text {
        ENTER {
        }

        TRY_AGAIN {
            set title "Please try again"
        }

        default {
            append title ": " $text
        }
    }

# prompt the user with $title, $keyid, $userid
# ...

    if {!$abort} {
        return $passphrases($keyid)
    }

    $params(token) -operation cancel
}


# print info about a key

proc printkey {ctx key} {
    foreach {k v} [$ctx -operation info-key \
                        -key       $key] {
        switch -- $k {
            subkeys {
                set i 0
                foreach subkey $v {
                    puts stdout "subkey #[incr i]"

                    foreach {k v} $subkey {
                        puts stdout [format "    %12.12s: %s" $k $v]
                    }
                }
            }

            default {
                puts stdout [format "    %12.12s: %s" $k $v]
            }
        }
    }
}



# 1. create a context for doing crypto


set ctx [gpgme::context]

$ctx -operation set                 \
     -property  passphrase-callback \
     -value     [list [namespace current]::passphrase]



# 2. if we have multiple keys to sign with, let the user pick which
#    ones to use


set keys {}
$ctx -operation  start-key \
     -secretonly true
while {[string compare [set key [$ctx -operation next-key]] ""]} {
    lappend keys $key
}
$ctx -operation done-key

switch -- [llength $keys] {
    0 {
# well, ignore this... they'll get an error later on
    }

    1 {
# okay to proceed...
    }

    default {
# present keys to user, reduce to a subset and then:

        $ctx -operation set     \
             -property  signers \
             -value     $keys
    }
}



# 3. let's make a detached signature


set input     "..."
set signature [$ctx -operation sign   \
                    -input     $input \
                    -mode      detach]



# 4. let's verify a detached signature


puts stdout "operation: verify"
foreach {k v} [$ctx -operation verify \
                    -input     $input \
                    -signature $signature] {
    switch -- $k {
        signatures {
            foreach signature $v {
                puts stdout "\ninfo on signature"
                foreach {k v} $signature {
                    switch -- $k {
                        key {
                            printkey $ctx $v
                        }

                        default {
                            puts stdout [format "    %12.12s: %s" $k $v]
                        }
                    }
                }
            }
            puts stdout ""
        }

        default {
            puts stdout [format "    %12.12s: %s" $k $v]
        }
    }
}



# 5. let's encipher something


set name fred@example.com

set rset [gpgme::recipient]
$rset -operation add   \
      -name      $name \
      -validity  full

# could add more, if we wanted...

set ciphertext [$ctx -operation  encrypt \
                     -input      $input  \
                     -recipients $rset]



# 6. let's decipher it


foreach {k v} [$ctx -operation decrypt \
                    -input $ciphertext \
                    -checkstatus yes] {
    puts stdout [format "    %12.12s: %s" $k $v]
}


 TOC 

References

[1] Callas, J., Donnerhacke, L., Finney, H. and R. Thayer, "OpenPGP Message Format", RFC 2440, November 1998 (TXT, HTML, XML).


 TOC 

Author's Address

  Marshall T. Rose
  Dover Beach Consulting, Inc.
  POB 255268
  Sacramento, CA 95865-5268
  US
Phone:  +1 916 483 8878
Fax:  +1 916 483 8848
EMail:  mrose@dbc.mtview.ca.us


 TOC 

Appendix A. Changes

A.1 Changes from 1.0



 TOC 

Appendix B. Copyrights

(c) 2002 Marshall T. Rose

Hold harmless the author, and any lawful use is allowed.



 TOC 

Index

C 
 callbacks
   passphrase
P 
 procedures
   context -operation cancel
   context -operation decrypt
   context -operation done-key
   context -operation done-trustitem
   context -operation encrypt
   context -operation get
   context -operation info
   context -operation info-key
   context -operation info-trustitem
   context -operation next-key
   context -operation next-trustitem
   context -operation set
   context -operation sign
   context -operation start-key
   context -operation start-trustitem
   context -operation verify
   context -operation wait
   gpgme::check_version
   gpgme::engine_check_version
   gpgme::get_engine_info
   gpgme::new
   gpgme::recipient
   recipients -operation add
   recipients -operation count
   recipients -operation info
   recipients -operation list