"No Such Algorithm" using ElGamal public key for encryption (please help repro?)

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 (please help repro?)

Michael P. Cosby
Environment:
J2SE 1.4.1 (unrestricted policy files installed)
BC 1.29 (bcpg, bcmail, and bcprov)
Javamail 1.3.2
java activation framework 1.0.2

  A search through the mailing list doesn't *seem* to show anyone else with my
particular problem, so hopefully someone can help me. Even if you can't help,
if you could manage to reproduce (or not reproduce) the problem that would
at least let me know if there's just something horribly wrong with my
environment.

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

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);

         MailcapCommandMap _mailcap =
             (MailcapCommandMap)CommandMap.getDefaultCommandMap();

     _mailcap.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature");
     _mailcap.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime");
     _mailcap.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature");
     _mailcap.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime");
     _mailcap.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");

     CommandMap.setDefaultCommandMap(_mailcap);

  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.