"No Such Algorithm" using ElGamal public key for encryption

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

"No Such Algorithm" using ElGamal public key for encryption

Michael P. Cosby
  A search through the mailing list doesn't *seem* to show anyone else with my
particular problem, so hopefully someone can help me.

  I'm trying to encrypt a message with a gpg-generated public key (encryption
key is ElGamal). The specific error I'm getting is:

pgptest$invalidKeyException: error making encrypted content.
         at pgptest.main(pgptest.java:144)
Caused by: java.security.NoSuchAlgorithmException: No such algorithm: 1.3.14.7.2.1.1
         at javax.crypto.SunJCE_b.c(DashoA6275)
         at javax.crypto.SunJCE_b.a(DashoA6275)
         at javax.crypto.Cipher.a(DashoA6275)
         at javax.crypto.Cipher.getInstance(DashoA6275)
         at org.bouncycastle.cms.CMSEnvelopedDataGenerator$RecipientInf.toRecipientInfo(CMSEnvelopedDataGenerator.java:184)
         at org.bouncycastle.cms.CMSEnvelopedDataGenerator.generate(CMSEnvelopedDataGenerator.java:403)
         at org.bouncycastle.cms.CMSEnvelopedDataGenerator.generate(CMSEnvelopedDataGenerator.java:446)
         at org.bouncycastle.mail.smime.SMIMEEnvelopedGenerator.make(SMIMEEnvelopedGenerator.java:109)
         at org.bouncycastle.mail.smime.SMIMEEnvelopedGenerator.generate(SMIMEEnvelopedGenerator.java:166)
         at pgptest.main(pgptest.java:132)

  Searching for that algorithm ID on google tells me it's ElGamal, and doing
the same in the bouncy castle source tells me it's defined in
org.bouncycastle.asm1.oiw.OIWObjectIdentifiers.java

  Other than that, I have no clue what's going on (except that my subKeyId
argument to addKeyTransRecipient may be incorrect - I'm guessing on what
value it actually wanted).

  Source code below:

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.Security;

// java
import java.io.ByteArrayInputStream;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.Iterator;
import java.util.Date;
import java.security.KeyStore;
import javax.mail.internet.MimeBodyPart;

// provider
import org.bouncycastle.jce.provider.BouncyCastleProvider;

// encryption
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;

// S/MIME
import org.bouncycastle.mail.smime.SMIMEEnvelopedGenerator;

// utility
import org.bouncycastle.bcpg.ArmoredInputStream;
import org.bouncycastle.bcpg.BCPGInputStream;
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;


public class pgptest {

  public static void main( String[] args ) {
  try {
  Security.addProvider(new BouncyCastleProvider());
  //Security.insertProviderAt(new BouncyCastleProvider(), 5);

  java.security.Provider[] provs = Security.getProviders();
  for( int i = 0; i < provs.length; i++ ){
  System.out.println( i + ". " + provs[i].getInfo() );
  }

  java.security.Provider prov = Security.getProvider( "BC" );
  // maybe we need an alias? not likely, but....
  prov.put( "Alg.Alias.Signature.1.3.14.7.2.1.1", "ElGamal" );

  String asciiArmoredKey = "-----BEGIN PGP PUBLIC KEY BLOCK----- " +
  "Version: GnuPG v1.4.1 (GNU/Linux)" +
  "  " +
  "mQGiBD1qZmMRBACgokYd6ckDuSlI30/prSsN9cldGYOkiUv/nkv34OT5t4DXiV88" +
  "7TeVq++DFNErEjhxOiDs4q34vtkilhg+8722zb4scoMZPYtqL7votrnHyjdirrz7" +
  "qi40NQeEpBg88WwUhXaPqqc+nlLgMXlyvo+zUBcJg02CthU/RiU/s3kVvwCg7AXA" +
  "pq0XblpFt4+mkYHKvxWc3F0D/j3t3E+lPKyWTRFhHpSlBBNJ3Av5VKL2mvYIed/D" +
  "ScZ/3Fd3aLao+MY8dRdUn539RKYISyY0NXLokDUAa7vWoEW0+7hGTSiJOoJ7KDnQ" +
  "KKg3/mvEdV7HydEkl8hzRmWDLubAAmwq5RWG0UHVjRFHJjmUh3ANCnoNcBxyUjzj" +
  "84msA/4gX3wLnyGQbLmGtcq0fZEWY6meON5lnQVEyhqt1i+TC9Xtv12CPJP3WQ2j" +
  "JskLw2qaEHnSsK2S9GmERTOx5/2ByJuteiv6oYAL06lMN8baJGHEneghgKgJGOJ4" +
  "QPWdRxaN3sHodDyTWzkiTBdqxkDbpsj/xnvxxLSuyiuqmnzAi7QzTWljaGFlbCBQ" +
  "LiBDb3NieSAoTWFpbiBLZXkpIDxtaWNoYWVsQGNvc2J5LmRocy5vcmc+iFkEExEC" +
  "ABkFAj1qZmMECwcDAgMVAgMDFgIBAh4BAheAAAoJEFnEORPWt9kgBIoAnRHhQA4Y" +
  "esCWEPHl13ckVMeUBv9KAJ9kXhgg8tEu9zCS32HAR3K9CxQGHLkBDQQ9amZkEAQA" +
  "o0A2+XZzJ95GXziQqraO63Yo7q6JkrOgDU2W1hkVYJRrk9Ai9sDqJwvVRTJfzM0m" +
  "fhhaxWG5eEYSfBAF34ET5SRVNICPf+ENGH/AbC6G2/QvjPy8r+kfk4NTm2d/nBri" +
  "AGe5cqqv8zpvY7Ww2FB+UPSB0AHdjkiMxsqy3ovAKesAAwUD/jo4XS/FnW/Vy/TI" +
  "7yd3zdbg5V+fDiip5Z7NjBNJgXtrY3tZHO84cJZ4ax9i0hDUWhpkFMcfQkW0Ibfg" +
  "LOtHoegpb4DFpt3YOmpNdd/2egVN6jWwhQkZee4xSc8hHZEcs2raLP/ndlh9/wFG" +
  "OyR0eu16LU5eafxZgUnbX/Hd6sa8iEYEGBECAAYFAj1qZmQACgkQWcQ5E9a32SCS" +
  "FgCgkKLRygOTKamrqi65/eeM+KHlwgEAnR/rNSXW4JASywJ8gewJpU8X9Whj " +
  "=Xv88 " +
  "-----END PGP PUBLIC KEY BLOCK-----";

/*
  try {
  pgp.encryptMessageTo( "this is my test message",
  new String[] { key } );
  } catch( pgp.invalidKeyException e ){
  System.out.println( e.getMessage() );
  e.printStackTrace();
  System.exit(0);
  }
*/

  // build the key ring from the public key file
  PGPPublicKeyRing keyRing = null;
  try {
  keyRing = new PGPPublicKeyRing( new ArmoredInputStream( new ByteArrayInputStream( fixAsciiArmor( asciiArmoredKey ).getBytes() ) ) );
  } catch( java.io.EOFException e ){
  String extra = "";
  if( asciiArmoredKey.indexOf( "+" ) == -1 ){
  extra = ". Is your user agent stripping out the '+' character?";
  }
  throw new invalidKeyException( "End of message reached before all required parts were found" + extra, e );
  } catch( java.io.IOException e ){
  throw new invalidKeyException( e.toString(), e );
  } catch( java.lang.NullPointerException e ){
  throw new invalidKeyException( "malformed key", e );
  }

  // pull out the encryption key
  PGPPublicKey encKey = null;
  Iterator i = keyRing.getPublicKeys();
  while( i.hasNext() ){
  PGPPublicKey p = (PGPPublicKey)i.next();
  if( p.isEncryptionKey() ){
  encKey = p;
  break;
  }
  }

  String message = "this is my test message";

  // create the subKeyId. Don't know if this is correct or not.
  java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate( 8 );
  SMIMEEnvelopedGenerator g = new SMIMEEnvelopedGenerator();
  buf.putLong( 0, encKey.getKeyID() );
  try {
  g.addKeyTransRecipient( encKey.getKey( "BC" ), buf.array() );
  } catch( org.bouncycastle.openpgp.PGPException e ){
  throw new invalidKeyException( e.getMessage(), e.getUnderlyingException() );
  } catch( java.security.NoSuchProviderException e ){
  throw new impossibleException();
  }

  MimeBodyPart msg = new MimeBodyPart();
  String contentType = null;
  String content = null;
  try {
  msg.setText( message );
  System.out.println( SMIMEEnvelopedGenerator.CAST5_CBC );
  System.out.println( SMIMEEnvelopedGenerator.RC2_CBC );
  MimeBodyPart mp = g.generate( msg,
  SMIMEEnvelopedGenerator.CAST5_CBC, "BC" );
  contentType = mp.getContentType();
  content = mp.getContent().toString();
  } catch( javax.mail.MessagingException e ){
  System.out.println( e.getMessage() );
  throw new impossibleException();
  } catch( org.bouncycastle.mail.smime.SMIMEException e ){
  throw new invalidKeyException( e.getMessage(),
  e.getUnderlyingException() );
  } catch( java.security.NoSuchProviderException e ){
  throw new impossibleException();
  } catch( java.security.NoSuchAlgorithmException e ){
  throw new impossibleException();
  } catch( java.io.IOException e ){
  System.out.println( e.getMessage() );
  throw new impossibleException();
  }

  System.out.println( content );
  } catch( invalidKeyException e ){
  System.out.println( e.getMessage() );
  e.printStackTrace();
  System.exit(0);
  }

  }

  private static String fixAsciiArmor( String in )
  throws invalidKeyException {

  Pattern p = Pattern.compile( "\\s*(-----BEGIN[^-]+-----)([^-]+)(-----END[^-]+-----).*", Pattern.DOTALL );

  Matcher m = p.matcher( in );
  if( !m.matches() ){
  throw new invalidKeyException(
  "Input does not match ascii armor specification (RFC 1991)" );
  }

  // this is very unsafe, becasue it's not in the spec at all...
  p = Pattern.compile( ".*?([\\w/=+]{10,}.*?)(=[\\w/=+]{4})\\s*", Pattern.DOTALL );
  Matcher m2 = p.matcher( m.group( 2 ) );
  if( !m2.matches() ){
  throw new invalidKeyException(
  "Input does not appear to match ascii armor specification (RFC 1991)" );
  }

  return m.group( 1 ) + "\n\n" + m2.group( 1 ).replaceAll( " ", "" ).trim() + "\n" + m2.group( 2 ).trim() + "\n" + m.group( 3 ) + "\n";
  }

  public static class invalidKeyException extends Exception {
  public invalidKeyException( String a ){
  super( a );
  }
  public invalidKeyException( String a, Throwable b ){
  super( a, b );
  }
  };

  public static class impossibleException extends RuntimeException {};

}

- Michael

--
Reality, n.
The state when you and your psychiatrist share the same delusions.