[Webfunds-commits] java/webfunds/ricardian ArmouredKeyException.java KeyUtil.java

Ian Grigg iang@cypherpunks.ai
Sun, 27 Aug 2000 17:56:40 -0400 (AST)


iang        00/08/27 17:56:40

  Modified:    webfunds/ricardian KeyUtil.java
  Added:       webfunds/ricardian ArmouredKeyException.java
  Log:
  Moved more PGPKey String processing utility methods into KeyUtil,
  taken from SignContractWizard.KeyPanel of yesterday.  Aim is to
  get all generic string processing handy tools in here, and possibly
  into something within OpenPGP some time so that we can manipulate
  the special cases more easily.
  Added Armoured exception which is used within these routines.

Revision  Changes    Path
1.5       +103 -15   java/webfunds/ricardian/KeyUtil.java

Index: KeyUtil.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/ricardian/KeyUtil.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- KeyUtil.java	2000/08/26 22:57:21	1.4
+++ KeyUtil.java	2000/08/27 21:56:40	1.5
@@ -13,16 +13,39 @@
     /** Static methods only. */
     private KeyUtil() {}
 
+    /**
+     *  Manifest constant for *internal* end of line for OpenPGP.
+     *  OpenPGP Signatures (and Ricardian Hashes) are calculated with
+     *  this as the end of line (but note that storage occurs with
+     *  the platform end of line).
+     */
+    public final static String eoln = "\r\n";  // how PGP cleartext is prepared
+    public static String getOpenPGPEndOfLine()  { return eoln; }
+
+    /**
+     *  Remember to convert on output.  This is here more for doco...
+     */
+    public static String getPlatformEndOfLine()
+                         { return System.getProperty("line.separator"); }
+
     public static PGPPublicKey publicKeyFromString(String s)
-        throws PGPException
+        throws ArmouredKeyException
     {
-        PGPArmoury armouredKey = new PGPArmoury(s);
-        PGPKeyFactory factory = new PGPKeyFactory();
-        Vector keys = factory.decodeKeys(armouredKey.getPayload());
-        PGPPublicKey pk = (PGPPublicKey)keys.elementAt(0);
-        return pk;
+        PGPKey key = keyFromString(s);
+        if (key instanceof PGPSecretKey)
+            throw new ArmouredKeyException(ArmouredKeyException.ISA_SECRET);
+        return (PGPPublicKey)key;
     }
         
+    public static PGPSecretKey secretKeyFromString(String s)
+        throws ArmouredKeyException
+    {
+        PGPKey key = keyFromString(s);
+        if (key instanceof PGPPublicKey)
+            throw new ArmouredKeyException(ArmouredKeyException.ISA_PUBLIC);
+        return (PGPSecretKey)key;
+    }
+        
     static final String PUBLIC_KEY_BLOCK = "PGP PUBLIC KEY BLOCK";
     static final String SECRET_KEY_BLOCK = "PGP PRIVATE KEY BLOCK";
             
@@ -41,8 +64,69 @@
        
     }
 
+    /**
+     *  Load up an armoured key from a string.
+     *  No checking other than that intrinsic in de-armouring and
+     *  insisting on one and one only key.
+     */
+    public static PGPKey keyFromString(String keyAsArmouredString)
+        throws ArmouredKeyException
+    {
+
+        if (keyAsArmouredString == null)
+            return null;
+
+        // check key
+        PGPArmoury akey;
+        try {
+            akey = new PGPArmoury(keyAsArmouredString);
+        } catch (IllegalArgumentException iae) {
+            throw new ArmouredKeyException(ArmouredKeyException.NOT_ARMOURED,
+                                   iae.getMessage());
+        }
+   
+        // get the unarmoured key
+        PGPKeyFactory factory = new PGPKeyFactory();
+        Vector keys;
+        try {
+            keys = factory.decodeKeys(akey.getPayload());
+        } catch (PGPFatalDataFormatException ex) {
+            throw new ArmouredKeyException(ArmouredKeyException.CORRUPT,
+                                   ex.getMessage());
+        }
+
+        if (keys.size() > 1)
+            throw new ArmouredKeyException(ArmouredKeyException.TOO_MANY_KEYS);
+        if (keys.size() < 1)
+            throw new ArmouredKeyException(ArmouredKeyException.EMPTY_PAYLOAD);
+
+        return (PGPKey)keys.elementAt(0);
+
+    }
+
+
+    /**
+     *  Read a Public Key from a string and return the key.
+     *  It must be signed by the signer, if provided (can be null).
+     *  It must be self-signed.
+     *  It must have the tag in it somewhere.
+     *  Additional sigs are stripped.
+     */
+    public static PGPPublicKey checkArmouredPublicKey(String armouredKey,
+                                          String tag,
+                                          PGPPublicKey signer)
+        throws StripKeyException, ArmouredKeyException
+    {
+       
+        PGPPublicKey pk = publicKeyFromString(armouredKey);
+        // check that the signer has signed
+     
+        return KeyUtil.stripAndVerifyKey(pk, tag, signer);
+    }
+
 
 
+
     /**
      * Strip the given key of all superfluous data. The key being returned
      * will have at most one userId (containing the string userIdTag) which 
@@ -56,7 +140,7 @@
      *         If the requested userId doesn't exist or is not self-signed or
      *         has multiple self-sigs or isn't signed by userIdSigner or has
      *         multiple sigs by userIdSigner (dunno if that's possible) or has
-     *         multiple matching userIds.
+     *         multiple matching userIds.  See the number in StripKeyException.
      */
     public static PGPPublicKey 
     stripAndVerifyKey(PGPPublicKey key, 
@@ -75,7 +159,7 @@
             // find the userId we want
             PGPUserID uid = findUserId(key, userIdTag);
             if (uid == null) 
-                throw new StripKeyException(
+                throw new StripKeyException(StripKeyException.NO_SUCH_USERID,
                     "UserId with tag (" + userIdTag + ") doesn't exist.");
 
             // strip sigs we don't want
@@ -88,9 +172,10 @@
                 if (sig.verify(key)) newSigs.addElement(sig);
             }
 
+            if (newSigs.size()==0)
+                throw new StripKeyException(StripKeyException.NOT_SELF_SIGNED);
             if (newSigs.size()!=1)
-                throw new StripKeyException(
-                    "Key is not self-signed or has multiple self-signatures.");
+                throw new StripKeyException(StripKeyException.TOO_MANY_SELFS);
 
             // (optional) retain userIdSigner sig
             if (userIdSigner!=null) {
@@ -99,9 +184,10 @@
                     if (sig.verify(userIdSigner)) newSigs.addElement(sig);
                 }
 
-                if (newSigs.size()!=2)
-                    throw new StripKeyException(
-                        "Key is not signed or has multiple sigs.");
+                if (newSigs.size()<2)
+                  throw new StripKeyException(StripKeyException.NOT_SIGNED);
+                if (newSigs.size()>2)
+                  throw new StripKeyException(StripKeyException.TOO_MANY_SIGS);
             }
 
             newSigs.trimToSize();
@@ -120,7 +206,8 @@
 
             // something went wrong, dunno what
             e.printStackTrace();
-            throw new StripKeyException(e.getMessage());
+            throw new StripKeyException(StripKeyException.CATCH_ALL,
+                                        e.getMessage());
         }
     }
 
@@ -201,7 +288,8 @@
             if( isMatch(s, userIdTag) ) {
                 if (res!=null) 
                     throw new StripKeyException(
-                        "Multiple matching userIds found.");
+                              StripKeyException.TOO_MANY_USERID,
+                              "Multiple matching userIds found.");
                 else
                     res = uid;
             }



1.1                  java/webfunds/ricardian/ArmouredKeyException.java

Index: ArmouredKeyException.java
===================================================================
/*
 * $Id: ArmouredKeyException.java,v 1.1 2000/08/27 21:56:40 iang Exp $
 *
 * Copyright (c) 2000 Systemics Inc on behalf of
 * the WebFunds Development Team.  All Rights Reserved.
 */
package webfunds.ricardian;

public class ArmouredKeyException
    extends Exception
{
    /**
     *  Known Contract failure modes detected.
     */
    public static final int   UNKNOWN         = 0,
                              CATCH_ALL       = 1, // catch all for other errors
                              ISA_SECRET      = 2, // not a public, got secret
                              ISA_PUBLIC      = 3, // not a secret, got public
                              NOT_ARMOURED    = 4, // not armoured in PGP style
                              EMPTY_PAYLOAD   = 5, // no keys found in armour
                              TOO_MANY_KEYS   = 6, // more than one
                              CORRUPT         = 7; // armour is corrupt or bad

    public static final String[] errors = {
                              "<not set, old Ex>",
                              "'miscellaneous error'",
                              "Is A Secret Key, Not Public!",
                              "Is A Public Key, Not Secret!",
                              "Not Signed By Signer",
                              "Empty Armoured Payload, No Keys Found",
                              "More Than One Key Found In Armoured Payload",
                              "Armour Is Corrupt",
                              };


    /**
     *  What error number has been set by the thrower.
     */
    protected int errno = UNKNOWN;
    public int    getErrno() { return errno; }

    public String getErrnoString()
    {
        if (! (0 <= errno && errno < errors.length) )
            return "<invalid: " + errno + ">";

        String e = errors[errno];

        return "(" + errno + ") " + ((e == null) ? "'unknown'" : e);
    }

    public String toString()
    {
        String s = "";
        if (errno > 0)
            s += getErrnoString() + ": ";
        s += super.toString();
        return s;
    }

    
    public ArmouredKeyException()                { super(); }
    /** @param msg string interpretation */
    public ArmouredKeyException(String msg)      { super(msg); }
    /** @param errno an identified error from public constants above */
    public ArmouredKeyException(int errno)       { super(); this.errno = errno;}
    public ArmouredKeyException(int e, String m) { super(m); this.errno = e; }

}