Package com.sun.star.pgp.version

Source Code of com.sun.star.pgp.version.PGP263x

/*************************************************************************
*
*  $RCSfile: PGP263x.java,v $
*
*  $Revision: 1.1.1.1 $
*
*  last change: $Author: hr $ $Date: 2000/09/18 16:16:50 $
*
*  The Contents of this file are made available subject to the terms of
*  either of the following licenses
*
*         - GNU Lesser General Public License Version 2.1
*         - Sun Industry Standards Source License Version 1.1
*
*  Sun Microsystems Inc., October, 2000
*
*  GNU Lesser General Public License Version 2.1
*  =============================================
*  Copyright 2000 by Sun Microsystems, Inc.
*  901 San Antonio Road, Palo Alto, CA 94303, USA
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public
*  License version 2.1, as published by the Free Software Foundation.
*
*  This library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*  Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
*  MA  02111-1307  USA
*
*
*  Sun Industry Standards Source License Version 1.1
*  =================================================
*  The contents of this file are subject to the Sun Industry Standards
*  Source License Version 1.1 (the "License"); You may not use this file
*  except in compliance with the License. You may obtain a copy of the
*  License at http://www.openoffice.org/license.html.
*
*  Software provided under this License is provided on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
*  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
*  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
*  See the License for the specific provisions governing your rights and
*  obligations concerning the Software.
*
*  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
*  Copyright: 2000 by Sun Microsystems, Inc.
*
*  All Rights Reserved.
*
*  Contributor(s): _______________________________________
*
*
************************************************************************/
package com.sun.star.pgp.version;

import com.sun.star.io.XInputStream;
import com.sun.star.io.XOutputStream;
import com.sun.star.io.IOException;
import com.sun.star.pgp.SignatureInfo;
import com.sun.star.pgp.UserInfo;
import com.sun.star.pgp.IPGP;
import com.sun.star.pgp.PGPException;
import com.sun.star.pgp.UserInfo;
import com.sun.star.pgp.ui.IPassPhraseDialog;

import java.io.*;
import java.util.*;



//==================================================================================================
public class PGP263x implements
       IPGP
{
  static final boolean DEBUG = false;
 
  private boolean    _bIsAvailable = false;
 
  private UserInfo[]  _publicUsers    = null;
  private UserInfo[]  _signatureUsers = null;
  private UserInfo  _defaultUser  = null;

  private String    _name = null;
 
  //______________________________________________________________________________________________
  private boolean getUserInfos( InputStream input throws java.io.IOException
  {
    String str;
   
    BufferedReader in = new BufferedReader( new InputStreamReader( input ) );
    // skip further two lines
    for ( int i = 2; i-- >= 0; )
    {
      if ((str = in.readLine()) == null)
        return false;
    }
   
    Vector lines = new Vector();
    while ((str = in.readLine()) != null)
    {
      lines.addElement( str );
    }

    // skip last one
    int nLen = lines.size() -1;
    if (nLen <= 0)
      return false;
    if (DEBUG)
      System.out.println( "# len="+nLen );

    // rows appear pubUser0, sigUser0, ...:/usr/local/jl/564a4/program/classes/classes.jar:/usr/local/jl/564a4/program/classes/one.jar:/usr/local/jl/564a4/program/classes/pgp.jar:/usr/local/jl/564a4/program/classes/sandbox.jar:/usr/local/jl/564a4/program/classes/swingall.jar:/usr/local/jl/564a4/program/classes/tkt.jar:/usr/local/jl/564a4/program/classes/uno.jar:/usr/local/jl/564a4/program/classes/usr.jar:/develop4/update/SRC564/564/tkt/unxsols2.pro/class:/develop4/update/SRC564/564/uno/unxsols2.pro/class:/develop4/update/SRC564/564/usr/unxsols2.pro/class:/develop4/update/SRC564/564/jlibs/unxsols2.pro/class:/usr/local/jl/src564/extensions/unxsols2.pro/class
    Vector pub = new Vector();
    Vector sig = new Vector();
    UserInfo lastPublic = null;
   
    for ( Enumeration enum = lines.elements(); nLen-- > 0; )
    {
      // type, bits/keyid, date, name <email>
      str = (String)enum.nextElement();

      boolean bPub = str.indexOf( "pub" ) == 0;
     
      UserInfo info = new UserInfo();      StringBuffer buf;
      char c;
      String keyId = null;
     
      // skip type
      int nStrPos = 0, nStrLen = str.length();
      while (nStrPos < nStrLen && str.charAt( nStrPos ) != ' ')
        ++nStrPos;
      while (nStrPos < nStrLen && str.charAt( nStrPos ) == ' ')
        ++nStrPos;

      if (bPub)
      {
        // read bits       new JXGridBagConstraints( 0, 0, 2, 1, 1.0, 0.0,

        buf = new StringBuffer();
        for ( ; nStrPos < nStrLen && (c = str.charAt( nStrPos )) != '/'; ++nStrPos )
          buf.append( c );
        info._bits = buf.toString();
       
        // skip '/'
        if (nStrPos < nStrLen)
          ++nStrPos;
      }
     
      // read keyId
       buf = new StringBuffer();
      for ( ; nStrPos < nStrLen && (c = str.charAt( nStrPos )) != ' '; ++nStrPos )
        buf.append( c );
      info._key = buf.toString();
      while (nStrPos < nStrLen && str.charAt( nStrPos ) == ' ')
        ++nStrPos;

      // if we read a sig and last public key is same user (with more info, e.g. bits)
      // then shortcut with info of this user
      if (!bPub &&
        lastPublic != null && lastPublic._key.equals( info._key ))
      {
        info = lastPublic;
      }
      else // else read rest of string
      {
        if (bPub)
        {
          // read date
          buf = new StringBuffer();
          for ( ; nStrPos < nStrLen && (c = str.charAt( nStrPos )) != ' '; ++nStrPos )
            buf.append( c );
          info._date = buf.toString();
          while (nStrPos < nStrLen && str.charAt( nStrPos ) == ' ')
            ++nStrPos;
        }
       
        // read full, name, eMail
        buf = new StringBuffer();
        StringBuffer name  = new StringBuffer();
        StringBuffer eMail = new StringBuffer();
        boolean bReadMail = false;
     
        for ( ; nStrPos < nStrLen; ++nStrPos )
        {
          c = str.charAt( nStrPos );
          switch (c)
          {
          case '<':
            bReadMail = true;
            break;
          case '>':
            bReadMail = false;
            break;
          default:
            if (bReadMail)
              eMail.append( c );
            else
              name.append( c );
          }
          buf.append( c );
        }
        info._fullName = buf.toString();
        info._eMail     = eMail.toString().trim();
        info._name     = name.toString().trim();
      }

      if (bPub)
        pub.addElement( info );
      else
        sig.addElement( info );
     
      if (DEBUG)
        System.out.println( "### info (" + (bPub ? "pub" : "sig") + ") :" + info );
    }

    // copy user infos to array
    int nPos = 0;
    _publicUsers = new UserInfo[pub.size()];
    for ( Enumeration enum = pub.elements(); enum.hasMoreElements(); )
      _publicUsers[nPos++] = (UserInfo)enum.nextElement();
   
    nPos = 0;
    _signatureUsers = new UserInfo[sig.size()];
    for ( Enumeration enum = sig.elements(); enum.hasMoreElements(); )
      _signatureUsers[nPos++] = (UserInfo)enum.nextElement();
   
    return true;
  }


  public String toString()
  {
    return _name;
  }

  public PGP263x()
  {
    try
    {
      // public ring
      Runtime runtime = Runtime.getRuntime();
      Process proc     
;
      BufferedReader in;
     
      proc = runtime.exec( new String[] { "pgp", "+batchmode", "+language=en", "-fkvv" } );

      BufferedReader err = new BufferedReader( new InputStreamReader( proc.getErrorStream() ) );

      _bIsAvailable = false;
     
      String str;
      while ((str = err.readLine()) != null)
      {
        int nIndex = str.indexOf( "2.6.3" );

        if (nIndex >= 0)
        {
          int nEnd = str.indexOf( nIndex, ' ' );
          if (nEnd < 0)
            nEnd = nIndex + 5;
          _name = "PGP " + str.substring( nIndex, nEnd );
          if (DEBUG)
            System.out.println( "### PGP name=\""+_name+"\"" );
         
          _bIsAvailable = getUserInfos( proc.getInputStream() );
          if (_signatureUsers.length > 0) // default user is first in list
            _defaultUser = _signatureUsers[0];

          break;
        }
      }
     
      proc.waitFor();
    }
    catch (InterruptedException exc)
    {
      if (DEBUG)
      {
        System.out.println( "### PGP263x InterruptedException: "+exc.getMessage() );
        exc.printStackTrace();
      }
    }
    catch (java.io.IOException exc)
    {
      if (DEBUG)
      {
        System.out.println( "### PGP263x IOException: "+exc.getMessage() );
        exc.printStackTrace();
      }
    }

    if (DEBUG && !_bIsAvailable)
      System.out.println( "### PGP263x not available!" );
  }

  //______________________________________________________________________________________________
  public UserInfo[] getPublicUserInfos()
  {
    return _publicUsers;
  }
  //______________________________________________________________________________________________
  public boolean hasPublicUserInfos()
  {
    return (_publicUsers != null && _publicUsers.length > 0);
  }
  //______________________________________________________________________________________________
  public UserInfo[] getSignatureUserInfos()
  {
    return _signatureUsers;
  }
  //______________________________________________________________________________________________
  public boolean hasSignatureUserInfos()
  {
    return (_signatureUsers != null && _signatureUsers.length > 0);
  }
  //______________________________________________________________________________________________
  public UserInfo getDefaultPrivateUserInfo()
  {
    return _defaultUser;
  }
  /**
   * checks if pgp 2.6.3 is available
   */
  //______________________________________________________________________________________________
  public boolean isAvailable()
  {
    return _bIsAvailable;
  }
  //______________________________________________________________________________________________
  void assumeAvailable() throws PGPException
  {
    if (! isAvailable())
      throw new PGPException( "PGP 2.6.3 is not available!" );
  }
  //______________________________________________________________________________________________
  private SignatureInfo processPGP( String params[], XInputStream input, XOutputStream output )
    throws IOException, PGPException
  {
    assumeAvailable();

    if (DEBUG)
    {
      System.out.print( "# cmd: " );
      for ( int i = 0; i < params.length; ++i )
        System.out.print( params[i]+" " );
      System.out.println();
    }

    // optional

    Runtime runtime = Runtime.getRuntime();
    Process proc  = null;
    SignatureInfo info =  null;
    try
    {
      proc = runtime.exec( params );
      // provide input
      OutputStream stdout = proc.getOutputStream();

      final int buffSize= 0x10000;
      byte[][] bytes= new byte[1][];
      int nRead;
      do
      {
        nRead = input.readBytes( bytes, buffSize );
        if (DEBUG)
        {
          System.out.print( "# writing stdout: " );
          byte ar[]= bytes[0];
          for ( int n = 0; n < nRead; ++n )
          {
            System.out.print( (char)ar[n] );
            if (n < ar.length-1)
              System.out.print( ", " );
          }
        }
        stdout.write( bytes[0], 0, nRead);
      }
      while (nRead == buffSize);

      if (DEBUG)
        System.out.println( "# input given. closing stdout" );
      stdout.close();
     
      // scan error stream
      BufferedReader stderr = new BufferedReader( new InputStreamReader( proc.getErrorStream() ) );
      String str;

      while ((str = stderr.readLine()) != null)
      {
        if (str.indexOf( "Error:" ) == 1)
        {
          proc.waitFor();
          throw new PGPException( str.substring( 7 ).trim() );
        }
      }
      // provide output data
      InputStream stdin = proc.getInputStream();
      byte buf[] = new byte[0x10000];
      while ((nRead = stdin.read( buf )) >= 0)
      {
        if (DEBUG)
        {
          System.out.print( "# writing output from stdin: " );
          for ( int n = 0; n < nRead; ++n )
          {
            System.out.print( (char)buf[n] );
            if (n < buf.length-1)
              System.out.print( ", " );
          }
        }
        //output.writeBytes( buf );
        // One could assume that the implementer of XOutputStream
        // checks for an EOF or a final token  that denotes the end
        // of the valid data package. Evidently this is not the
        // case therefore we can't blindly write the whole array but
        // have to write the same number of bytes as received from
        // PGP in the InputS tream (Process.getInputStream()).
        // If we wrote the whole buffer, then all the data are interpreted
        // as pertaining to the mail.
       
        // workaround: create a buffer with the size of the valid data block
        // and use it in output.writeBytes rather then "buf"
        if(nRead == -1)
          output.writeBytes(buf);
        else{
          byte accurate[]=new byte[nRead];
          System.arraycopy( buf, 0, accurate, 0, nRead);
          output.writeBytes( accurate);
        }
        // ------------------------------------------------------------------
      }
      if (DEBUG)
        System.out.println( "# output given." );

      if (DEBUG && info != null)
      {
        if (info._bSignatureChecked)
          System.out.println( "# "+(info._bMessageVerified ? "Good" : "Bad")+" signature for user "+info._userId+"!" );
        else
          System.out.println( "# user "+info._userId+" could not be verified!" );
      }

      if (DEBUG)
        System.out.println( "### waiting for process to end..." );
      proc.waitFor();
      if (DEBUG)
      {
        System.out.println( "### process died." );
        System.out.flush();
      }
    }
    catch (InterruptedException exc)
    {
      throw new PGPException( exc.getMessage() );
    }
    catch (java.io.IOException exc)
    {
      throw new IOException( exc.getMessage(), null );
    }
    return info;
  }
 
  /**
   * encryption: Recipients (Key-Id) must exist in public key ring
   * @param Recipients key Ids
   * output is always in ascii radix
   */
  //______________________________________________________________________________________________
  public void encryptAndSign( UserInfo Signer, String Signersphrase, UserInfo Recipients[],
                XInputStream PlainText, XOutputStream CipherText )
    throws IOException, PGPException
  {
    String params[] = new String[Recipients.length +8];
    int nPos = 0;
    params[nPos++] = "pgp";
    params[nPos++] = "+batchmode";
    params[nPos++] = "+language=en";
    params[nPos++] = "-feas";
    for ( int i = Recipients.length; i-- > 0; )
      params[nPos++] = "0x" + Recipients[i]._key;
    params[nPos++] = "-u";
    params[nPos++] = "0x" + Signer._key;
    params[nPos++] = "-z";
    params[nPos++]= Signersphrase;
   
    processPGP( params, PlainText, CipherText );
  }
  //______________________________________________________________________________________________
  public void encrypt( UserInfo Recipients[], XInputStream PlainText, XOutputStream CipherText )
    throws IOException, PGPException
  {
    String params[] = new String[Recipients.length +4];
    int nPos = 0;
    params[nPos++] = "pgp";
    params[nPos++] = "+batchmode";
    params[nPos++] = "+language=en";
    params[nPos++] = "-fea";
    for ( int i = Recipients.length; i-- > 0; )
      params[nPos++] = "0x" + Recipients[i]._key;
   
    processPGP( params, PlainText, CipherText );
  }
  //______________________________________________________________________________________________
  /** The pgp option +clearsig=on is default since pgp 2.5.
   */
  public void sign( UserInfo Signer, String Signersphrase, boolean bOutputIsAscii,
            XInputStream PlainText, XOutputStream SignedText )
    throws IOException, PGPException
  {
    String params[] = bOutputIsAscii
      ? new String[] { "pgp", "+batchmode", "+language=en", "-fast",
               "-u", "0x" + Signer._key, "-z", Signersphrase }
      : new String[] { "pgp", "+batchmode", "+language=en", "-fas",
               "-u", "0x" + Signer._key, "-z", Signersphrase };
   
    processPGP( params, PlainText, SignedText );
  }
  /**
   * conventional encryption
   * output is always in ascii radix
   */
  //______________________________________________________________________________________________
  public void encryptConv( String Passphrase, XInputStream PlainText, XOutputStream CipherText )
    throws IOException, PGPException
  {
    String params[] = new String[] { "pgp", "+batchmode", "+language=en", "-fac",
                     "-z",  Passphrase  };
   
    processPGP( params, PlainText, CipherText );
  }
  //______________________________________________________________________________________________
  public void encryptAndSignConv( UserInfo Signer, String Signersphrase, String Passphrase,
                  XInputStream PlainText, XOutputStream CipherText )
    throws IOException, PGPException
  {
    String params[] = new String[] { "pgp", "+batchmode", "+language=en", "-fasc",
                     "-u", "0x" + Signer._key, "-z", Signersphrase,
                     "-z", Passphrase};
   
    processPGP( params, PlainText, CipherText );
  }

  /**
   * The method doens't explicitly close the input or output stream.
   */
//    public SignatureInfo decryptAndVerify( String Passphrase,
//                         XInputStream CipherText, XOutputStream PlainText )
//      throws classic.com.sun.star.io.IOException, PGPException
//    {
//      String params[] = new String[] { "pgp", "+batchmode", "+language=en", "-f",
//                       "-z", Passphrase };
   
//      return processPGP( params, CipherText, PlainText );
//    }

  public SignatureInfo decryptAndVerify( IPassPhraseDialog dialog,
                   XInputStream aCipherText, XOutputStream aPlainText )
    throws IOException, PGPException
  {

    assumeAvailable();
     SignatureInfo info =  null;

      try
      {
      byte[][] readBuff= new byte[1][];
      int nRead;
      int nSizeLine=100;

      // read in the first 100 bytes
      nRead = aCipherText.readBytes( readBuff, nSizeLine );
   
      // Check if a pass phrase is required. This is not the case if
      // the text has just been signed and not encrypted. To find out
      // we look for the string "BEGIN PGP SIGNED MESSAGE". This only works
      // if pgp was used with options -sat !!!!
      // If a pass phrase is required than prompt the user for it
      String passPhrase= null;
      String text= new String( readBuff[0], 0, nSizeLine); //uses Default byte to character encoding
      if( text.indexOf("BEGIN PGP SIGNED MESSAGE") == -1){
        passPhrase= dialog.getPassPhrase();
        if( passPhrase == null)
          return null;
      }
      //---
      String params[] = new String[] { "pgp", "+batchmode", "+language=en", "-f",
                       "-z", passPhrase };
      Runtime runtime = Runtime.getRuntime();
      Process proc  = null;
     
      proc = runtime.exec( params );
      OutputStream stdout = proc.getOutputStream();
     
      // fed pgp with the actual text
      stdout.write( readBuff[0], 0, nRead); // write the formerly read data
      do
      {
        nRead = aCipherText.readBytes( readBuff, 0x10000 );
        if (DEBUG)
        {
          System.out.print( "# writing stdout: " );
          byte ar[] = readBuff[0];
          for ( int n = 0; n < nRead; ++n )
          {
            System.out.print( (char)ar[n] );
            if (n < ar.length-1)
              System.out.print( ", " );
          }
        }
        stdout.write( readBuff[0], 0, nRead);
      }
      while (nRead == 0x10000);
      stdout.close();
     
      // scan error stream
      BufferedReader stderr = new BufferedReader( new InputStreamReader( proc.getErrorStream() ) );
      String str;
     
      while ((str = stderr.readLine()) != null)
      {
        if (str.indexOf( "Error:" ) == 1)
        {
          proc.waitFor();
          throw new PGPException( str.substring( 7 ).trim() );
        }
        /* If text was signed then there is an output like:
         * Good signature from user "Joachim Lingner <jlingner@gmx.de>".
         */       
        else if (str.indexOf( "signature from user" ) != -1)
        {
          String user = str.substring( str.indexOf( '\"' )-1, str.lastIndexOf( '\"' ) ).trim();
          info = new SignatureInfo();
          info._userId      = user;
          info._bSignatureChecked = true;
          info._bMessageVerified  = (str.indexOf( "Good" ) == 0);
        }
        else if (str.indexOf( "Key matching expected Key ID" ) == 1)
        {         
          String user = str.substring( 28, str.indexOf( "not found" ) ).trim();
          info = new SignatureInfo();
          info._userId      = user;
          info._bSignatureChecked = false;
          info._bMessageVerified  = false;
        }
      }
      // provide output data
      InputStream stdin = proc.getInputStream();
      byte buf[] = new byte[0x10000];
      while ((nRead = stdin.read( buf )) >= 0)
      {
        if (DEBUG)
        {
          System.out.print( "# writing output from stdin: " );
          for ( int n = 0; n < nRead; ++n )
          {
            System.out.print( (char)buf[n] );
            if (n < buf.length-1)
              System.out.print( ", " );
          }
        }
        //output.writeBytes( buf );
        // One could assume that the implementer of XOutputStream
        // checks for an EOF or a final token  that denotes the end
        // of the valid data package. Evidently this is not the
        // case therefore we can't blindly write the whole array but
        // have to write the same number of bytes as received from
        // PGP in the InputS tream (Process.getInputStream()).
        // If we wrote the whole buffer, then all the data are interpreted
        // as pertaining to the mail.
       
        // workaround: create a buffer with the size of the valid data block
        // and use it in output.writeBytes rather then "buf"
        if(nRead == -1)
          aPlainText.writeBytes(buf);
        else{
          byte accurate[]=new byte[nRead];
          System.arraycopy( buf, 0, accurate, 0, nRead);
          aPlainText.writeBytes( accurate);
        }
        // ------------------------------------------------------------------
      }
      if (DEBUG)
        System.out.println( "# output given." );

      if (DEBUG && info != null)
      {
        if (info._bSignatureChecked)
          System.out.println( "# "+(info._bMessageVerified ? "Good" : "Bad")+" signature for user "+info._userId+"!" );
        else
          System.out.println( "# user "+info._userId+" could not be verified!" );
      }

      if (DEBUG)
        System.out.println( "### waiting for process to end..." );
      proc.waitFor();
      if (DEBUG)
      {
        System.out.println( "### process died." );
        System.out.flush();
      }
    }
    catch (InterruptedException exc)
    {
      throw new PGPException( exc.getMessage() );
    }
    catch (java.io.IOException exc)
    {
      throw new IOException( exc.getMessage(), null );
    }
    return info;
    }
}







TOP

Related Classes of com.sun.star.pgp.version.PGP263x

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.