Пример #1
0
 AlgorithmParameters implGetParameters() {
   AlgorithmParameters params = null;
   if (salt == null) {
     // Cipher is not initialized with parameters;
     // follow the recommendation in PKCS12 v1.0
     // section B.4 to generate salt and iCount.
     salt = new byte[DEFAULT_SALT_LENGTH];
     SunJCE.getRandom().nextBytes(salt);
     iCount = DEFAULT_COUNT;
   }
   PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
   try {
     params = AlgorithmParameters.getInstance(pbeAlgo, "SunJCE");
   } catch (GeneralSecurityException gse) {
     // should never happen
     throw new RuntimeException("SunJCE provider is not configured properly");
   }
   try {
     params.init(pbeSpec);
   } catch (InvalidParameterSpecException ipse) {
     // should never happen
     throw new RuntimeException("PBEParameterSpec not supported");
   }
   return params;
 }
Пример #2
0
  private void setSignatureParameters(Signature var1, DEREncodable var2)
      throws NoSuchAlgorithmException, SignatureException, InvalidKeyException {
    if (var2 != null) {
      if (!DERNull.INSTANCE.equals(var2)) {
        String var3 = var1.getAlgorithm();
        Provider var4 = var1.getProvider();
        AlgorithmParameters var5 = AlgorithmParameters.getInstance(var3, var4);

        try {
          byte[] var6 = var2.getDERObject().getDEREncoded();
          var5.init(var6);
        } catch (IOException var17) {
          StringBuilder var9 = (new StringBuilder()).append("IOException decoding parameters: ");
          String var10 = var17.getMessage();
          String var11 = var9.append(var10).toString();
          throw new SignatureException(var11);
        }

        if (var1.getAlgorithm().endsWith("MGF1")) {
          try {
            AlgorithmParameterSpec var7 = var5.getParameterSpec(PSSParameterSpec.class);
            var1.setParameter(var7);
          } catch (GeneralSecurityException var16) {
            StringBuilder var13 = (new StringBuilder()).append("Exception extracting parameters: ");
            String var14 = var16.getMessage();
            String var15 = var13.append(var14).toString();
            throw new SignatureException(var15);
          }
        }
      }
    }
  }
Пример #3
0
 /**
  * Generate a spec from a curve name
  *
  * @return null if fail
  */
 private static ECParameterSpec genSpec(String name) {
   // convert the ECGenParameterSpecs to ECParameterSpecs for several reasons:
   // 1) to check availability
   // 2) efficiency
   // 3) SigUtil must cast the AlgorithmParameterSpec to a ECParameterSpec
   //    to convert a I2P key to a Java key. Sadly, a ECGenParameterSpec
   //    is not a ECParameterSpec.
   try {
     AlgorithmParameters ap;
     try {
       ap = AlgorithmParameters.getInstance("EC");
     } catch (Exception e) {
       if (BC_AVAILABLE) {
         log("Named curve " + name + " is not available, trying BC", e);
         ap = AlgorithmParameters.getInstance("EC", "BC");
         log("Fallback to BC worked for named curve " + name);
       } else {
         throw e;
       }
     }
     ECGenParameterSpec ecgps = new ECGenParameterSpec(name);
     ap.init(ecgps);
     ECParameterSpec rv = ap.getParameterSpec(ECParameterSpec.class);
     log("Named curve " + name + " loaded");
     return rv;
   } catch (Exception e) {
     log("Named curve " + name + " is not available", e);
     return null;
   }
 }
  /**
   * @tests javax.crypto.Cipher#getParameters()
   * @tests javax.crypto.Cipher#init(int, java.security.Key, java.security.AlgorithmParameters,
   *     java.security.SecureRandom)
   */
  public void test_getParameters() throws Exception {

    /*
     * If this test is changed, implement the following:
     * test_initILjava_security_KeyLjava_security_AlgorithmParametersLjava_security_SecureRandom()
     */

    SecureRandom sr = new SecureRandom();
    Cipher cipher = null;

    byte[] apEncoding = null;

    byte[] iv = new byte[8];
    sr.nextBytes(iv);

    AlgorithmParameters ap = AlgorithmParameters.getInstance("DESede");
    ap.init(iv, "RAW");
    apEncoding = ap.getEncoded("ASN.1");

    cipher = Cipher.getInstance(algorithm + "/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, cipherKey, ap, sr);

    byte[] cipherParmsEnc = cipher.getParameters().getEncoded("ASN.1");
    assertTrue("Parameters differ", Arrays.equals(apEncoding, cipherParmsEnc));
  }
Пример #5
0
 /**
  * Method getAlgParam.
  *
  * @return AlgorithmParameters
  * @param jceName The name of the algorithm parameters which may depend on the provider
  */
 public AlgorithmParameters getAlgParam(String jceName)
     throws NoSuchAlgorithmException, IOException {
   if (this.param == null) {
     return null;
   }
   AlgorithmParameters ap = AlgorithmParameters.getInstance(jceName);
   ap.init(this.param.getValue());
   return ap;
 }
Пример #6
0
 public AlgorithmParameters getAlgParameters() {
   if (params == null && encodedParams != null) {
     try {
       params = AlgorithmParameters.getInstance(getAlgName());
       params.init(encodedParams);
     } catch (NoSuchAlgorithmException ignore) {
       // FIXME throw exception?
     } catch (IOException ignore) {
     }
   }
   return params;
 }
  private static byte[] testParams(AlgorithmParameters rc2Params, RC2ParameterSpec rc2Spec)
      throws Exception {

    // test getParameterSpec returns object equal to input
    rc2Params.init(rc2Spec);
    RC2ParameterSpec rc2OtherSpec =
        (RC2ParameterSpec) rc2Params.getParameterSpec(RC2ParameterSpec.class);
    if (!rc2Spec.equals(rc2OtherSpec)) {
      throw new Exception("AlgorithmParameterSpecs should be equal");
    }

    // test RC2ParameterSpec with RC2 Cipher
    Cipher rc2Cipher = Cipher.getInstance("RC2/CBC/PKCS5PADDING", "SunJCE");
    rc2Cipher.init(
        Cipher.ENCRYPT_MODE, new SecretKeySpec("secret".getBytes("ASCII"), "RC2"), rc2Spec);

    // get IV
    byte[] iv = rc2Cipher.getIV();
    if (!Arrays.equals(iv, rc2Spec.getIV())) {
      throw new Exception("ivs should be equal");
    }

    // test encoding and decoding
    byte[] encoded = rc2Params.getEncoded();
    AlgorithmParameters params = AlgorithmParameters.getInstance("RC2");
    params.init(encoded);

    // test RC2 AlgorithmParameters with RC2 Cipher
    rc2Cipher.init(
        Cipher.ENCRYPT_MODE, new SecretKeySpec("secret".getBytes("ASCII"), "RC2"), params);

    // get IV
    iv = rc2Cipher.getIV();
    if (!Arrays.equals(iv, rc2Spec.getIV())) {
      throw new Exception("ivs should be equal");
    }
    return encoded;
  }
Пример #8
0
  public void testAES256CCM() throws Exception {
    byte[] data = "Eric H. Echidna".getBytes();
    ASN1ObjectIdentifier macAlg = CMSAlgorithm.AES256_CCM;
    AlgorithmParameters algParams = AlgorithmParameters.getInstance("CCM", BC);

    algParams.init(new CCMParameters(Hex.decode("000102030405060708090a0b"), 16).getEncoded());

    CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();

    X509CertificateHolder origCert = new X509CertificateHolder(_origCert.getEncoded());

    adGen.setOriginatorInfo(new OriginatorInfoGenerator(origCert).generate());

    adGen.addRecipientInfoGenerator(
        new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC));

    CMSAuthenticatedData ad =
        adGen.generate(
            new CMSProcessableByteArray(data),
            new JceCMSMacCalculatorBuilder(macAlg)
                .setAlgorithmParameters(algParams)
                .setProvider(BC)
                .build());

    assertTrue(ad.getOriginatorInfo().getCertificates().getMatches(null).contains(origCert));

    RecipientInformationStore recipients = ad.getRecipientInfos();

    assertEquals(ad.getMacAlgOID(), macAlg.getId());

    Collection c = recipients.getRecipients();

    assertEquals(1, c.size());

    Iterator it = c.iterator();

    while (it.hasNext()) {
      RecipientInformation recipient = (RecipientInformation) it.next();

      assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());

      byte[] recData =
          recipient.getContent(
              new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC));

      assertTrue(Arrays.equals(data, recData));
      assertEquals(16, ad.getMac().length);
      assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
    }
  }
Пример #9
0
  protected AlgorithmParameters engineGetParameters() {
    if (engineParams == null) {
      if (paramSpec != null) {
        try {
          engineParams = helper.createAlgorithmParameters("OAEP");
          engineParams.init(paramSpec);
        } catch (Exception e) {
          throw new RuntimeException(e.toString());
        }
      }
    }

    return engineParams;
  }
  protected AlgorithmParameters engineGetParameters() {
    if (engineParams == null) {
      if (paramSpec != null) {
        try {
          engineParams = AlgorithmParameters.getInstance("OAEP", "DFBC");
          engineParams.init(paramSpec);
        } catch (Exception e) {
          throw new RuntimeException(e.toString());
        }
      }
    }

    return engineParams;
  }
Пример #11
0
  /*
   * Generate PBE Algorithm Parameters
   */
  private AlgorithmParameters getAlgorithmParameters(String algorithm) throws IOException {
    AlgorithmParameters algParams = null;

    // create PBE parameters from salt and iteration count
    PBEParameterSpec paramSpec = new PBEParameterSpec(getSalt(), iterationCount);
    try {
      algParams = AlgorithmParameters.getInstance(algorithm);
      algParams.init(paramSpec);
    } catch (Exception e) {
      IOException ioe = new IOException("getAlgorithmParameters failed: " + e.getMessage());
      ioe.initCause(e);
      throw ioe;
    }
    return algParams;
  }
Пример #12
0
 // see JCE spec
 protected AlgorithmParameters engineGetParameters() {
   if (iv == null) {
     return null;
   }
   IvParameterSpec ivSpec = new IvParameterSpec(iv);
   try {
     AlgorithmParameters params =
         AlgorithmParameters.getInstance(keyAlgorithm, P11Util.getSunJceProvider());
     params.init(ivSpec);
     return params;
   } catch (GeneralSecurityException e) {
     // NoSuchAlgorithmException, NoSuchProviderException
     // InvalidParameterSpecException
     throw new ProviderException("Could not encode parameters", e);
   }
 }
Пример #13
0
  protected AlgorithmParameters engineGetParameters() {
    if (engineParam == null) {
      if (engineParams != null) {
        String name = "IES";

        try {
          engineParam = AlgorithmParameters.getInstance(name, BouncyCastleProvider.PROVIDER_NAME);
          engineParam.init(engineParams);
        } catch (Exception e) {
          throw new RuntimeException(e.toString());
        }
      }
    }

    return engineParam;
  }
  private AlgorithmParameters getParameters() throws NoSuchAlgorithmException {
    AlgorithmParameters ap = AlgorithmParameters.getInstance(this.getAlgName());
    ByteArrayOutputStream bOut = new ByteArrayOutputStream();
    DEROutputStream dOut = new DEROutputStream(bOut);

    try {
      dOut.writeObject(infoObj.getEncryptionAlgorithm().getParameters());
      dOut.close();

      ap.init(bOut.toByteArray());
    } catch (IOException e) {
      throw new NoSuchAlgorithmException("unable to parse parameters");
    }

    return ap;
  }
Пример #15
0
  private void tryKekAlgorithm(SecretKey kek, ASN1ObjectIdentifier algOid, byte[] encodedParameters)
      throws NoSuchAlgorithmException, NoSuchProviderException, CMSException,
          OperatorCreationException, IOException {
    byte[] data = "Eric H. Echidna".getBytes();

    CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();

    byte[] kekId = new byte[] {1, 2, 3, 4, 5};

    adGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId, kek).setProvider(BC));

    AlgorithmParameters algParams =
        AlgorithmParameters.getInstance(CMSAlgorithm.DES_EDE3_CBC.getId(), "BC");

    algParams.init(encodedParameters);

    CMSAuthenticatedData ad =
        adGen.generate(
            new CMSProcessableByteArray(data),
            new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC)
                .setAlgorithmParameters(algParams)
                .setProvider(BC)
                .build());

    RecipientInformationStore recipients = ad.getRecipientInfos();

    Collection c = recipients.getRecipients();
    Iterator it = c.iterator();

    assertEquals(ad.getMacAlgOID(), CMSAuthenticatedDataGenerator.DES_EDE3_CBC);
    assertEquals(
        ad.getMacAlgorithm().getParameters(), ASN1Primitive.fromByteArray(encodedParameters));

    if (it.hasNext()) {
      RecipientInformation recipient = (RecipientInformation) it.next();

      assertEquals(recipient.getKeyEncryptionAlgOID(), algOid.getId());

      byte[] recData = recipient.getContent(new JceKEKAuthenticatedRecipient(kek).setProvider(BC));

      assertTrue(Arrays.equals(data, recData));
      assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
    } else {
      fail("no recipient found");
    }
  }
Пример #16
0
  protected AlgorithmParameters engineGetParameters() {
    if (engineParams == null) {
      if (pbeSpec != null) {
        try {
          AlgorithmParameters engineParams =
              AlgorithmParameters.getInstance(pbeAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
          engineParams.init(pbeSpec);

          return engineParams;
        } catch (Exception e) {
          return null;
        }
      }
    }

    return engineParams;
  }
Пример #17
0
  private void testParameters() throws Exception {
    AlgorithmParameterGenerator a = AlgorithmParameterGenerator.getInstance("DSA", "BC");
    a.init(512, random);
    AlgorithmParameters params = a.generateParameters();

    byte[] encodeParams = params.getEncoded();

    AlgorithmParameters a2 = AlgorithmParameters.getInstance("DSA", "BC");
    a2.init(encodeParams);

    // a and a2 should be equivalent!
    byte[] encodeParams_2 = a2.getEncoded();

    if (!areEqual(encodeParams, encodeParams_2)) {
      fail("encode/decode parameters failed");
    }

    DSAParameterSpec dsaP = (DSAParameterSpec) params.getParameterSpec(DSAParameterSpec.class);

    KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "BC");
    g.initialize(dsaP, new SecureRandom());
    KeyPair p = g.generateKeyPair();

    PrivateKey sKey = p.getPrivate();
    PublicKey vKey = p.getPublic();

    Signature s = Signature.getInstance("DSA", "BC");
    byte[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};

    s.initSign(sKey);

    s.update(data);

    byte[] sigBytes = s.sign();

    s = Signature.getInstance("DSA", "BC");

    s.initVerify(vKey);

    s.update(data);

    if (!s.verify(sigBytes)) {
      fail("DSA verification failed");
    }
  }
  /**
   * return an AlgorithmParameters object representing the parameters to the key derivation
   * algorithm to the recipient.
   *
   * @return AlgorithmParameters object, null if there aren't any.
   */
  public AlgorithmParameters getKeyDerivationAlgParameters(Provider provider) {
    try {
      if (info.getKeyDerivationAlgorithm() != null) {
        DEREncodable params = info.getKeyDerivationAlgorithm().getParameters();
        if (params != null) {
          AlgorithmParameters algP =
              AlgorithmParameters.getInstance(
                  info.getKeyDerivationAlgorithm().getObjectId().toString(), provider);

          algP.init(params.getDERObject().getEncoded());

          return algP;
        }
      }

      return null;
    } catch (Exception e) {
      throw new RuntimeException("exception getting encryption parameters " + e);
    }
  }
Пример #19
0
    protected AlgorithmParameters engineGenerateParameters() {
      byte[] iv = new byte[8];

      if (random == null) {
        random = new SecureRandom();
      }

      random.nextBytes(iv);

      AlgorithmParameters params;

      try {
        params = AlgorithmParameters.getInstance("CAST5", BouncyCastleProvider.PROVIDER_NAME);
        params.init(new IvParameterSpec(iv));
      } catch (Exception e) {
        throw new RuntimeException(e.getMessage());
      }

      return params;
    }
Пример #20
0
  protected AlgorithmParameters engineGetParameters() {
    if (engineParams == null) {
      if (ivParam != null) {
        String name = cipher.getUnderlyingCipher().getAlgorithmName();

        if (name.indexOf('/') >= 0) {
          name = name.substring(0, name.indexOf('/'));
        }

        try {
          engineParams = AlgorithmParameters.getInstance(name, BouncyCastleProvider.PROVIDER_NAME);
          engineParams.init(ivParam.getIV());
        } catch (Exception e) {
          throw new RuntimeException(e.toString());
        }
      }
    }

    return engineParams;
  }
Пример #21
0
    protected AlgorithmParameters engineGenerateParameters() {
      byte[] iv = new byte[8];

      if (random == null) {
        random = new SecureRandom();
      }

      random.nextBytes(iv);

      AlgorithmParameters params;

      try {
        params = createParametersInstance("DES");
        params.init(new IvParameterSpec(iv));
      } catch (Exception e) {
        throw new RuntimeException(e.getMessage());
      }

      return params;
    }
  /**
   * @tests javax.crypto.Cipher#getIV()
   * @tests javax.crypto.Cipher#init(int, java.security.Key, java.security.AlgorithmParameters)
   */
  public void test_getIV() throws Exception {
    /*
     * If this test is changed, implement the following:
     * test_initILjava_security_KeyLjava_security_AlgorithmParameters()
     */

    SecureRandom sr = new SecureRandom();
    Cipher cipher = null;

    byte[] iv = new byte[8];
    sr.nextBytes(iv);
    AlgorithmParameters ap = AlgorithmParameters.getInstance(algorithm);
    ap.init(iv, "RAW");

    cipher = Cipher.getInstance(algorithm + "/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, cipherKey, ap);

    byte[] cipherIV = cipher.getIV();

    assertTrue("IVs differ", Arrays.equals(cipherIV, iv));
  }
Пример #23
0
  private void testRandom(int size) throws Exception {
    AlgorithmParameterGenerator a = AlgorithmParameterGenerator.getInstance("ElGamal", "BC");
    a.init(size, new SecureRandom());
    AlgorithmParameters params = a.generateParameters();

    byte[] encodeParams = params.getEncoded();

    AlgorithmParameters a2 = AlgorithmParameters.getInstance("ElGamal", "BC");
    a2.init(encodeParams);

    // a and a2 should be equivalent!
    byte[] encodeParams_2 = a2.getEncoded();

    if (!areEqual(encodeParams, encodeParams_2)) {
      fail(this.getName() + ": encode/decode parameters failed");
    }

    DHParameterSpec elP = (DHParameterSpec) params.getParameterSpec(DHParameterSpec.class);

    testGP(size, 0, elP.getG(), elP.getP());
  }
Пример #24
0
 /*
  * parse Algorithm Parameters
  */
 private AlgorithmParameters parseAlgParameters(DerInputStream in) throws IOException {
   AlgorithmParameters algParams = null;
   try {
     DerValue params;
     if (in.available() == 0) {
       params = null;
     } else {
       params = in.getDerValue();
       if (params.tag == DerValue.tag_Null) {
         params = null;
       }
     }
     if (params != null) {
       algParams = AlgorithmParameters.getInstance("PBE");
       algParams.init(params.toByteArray());
     }
   } catch (Exception e) {
     IOException ioe = new IOException("parseAlgParameters failed: " + e.getMessage());
     ioe.initCause(e);
     throw ioe;
   }
   return algParams;
 }
Пример #25
0
  /**
   * Decrypts the specified encrypted Content Encryption Key (CEK).
   *
   * @param priv The private RSA key. Must not be {@code null}.
   * @param encryptedCEK The encrypted Content Encryption Key (CEK) to decrypt. Must not be {@code
   *     null}.
   * @return The decrypted Content Encryption Key (CEK).
   * @throws RuntimeException If decryption failed.
   */
  public static SecretKey decryptCEK(final RSAPrivateKey priv, final byte[] encryptedCEK) {

    try {
      AlgorithmParameters algp =
          AlgorithmParameters.getInstance("OAEP", new BouncyCastleProvider());
      AlgorithmParameterSpec paramSpec =
          new OAEPParameterSpec(
              "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
      algp.init(paramSpec);
      Cipher cipher =
          Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding", new BouncyCastleProvider());
      cipher.init(Cipher.DECRYPT_MODE, priv, algp);
      return new SecretKeySpec(cipher.doFinal(encryptedCEK), "AES");

    } catch (Exception e) {
      // java.security.NoSuchAlgorithmException
      // java.security.NoSuchPaddingException
      // java.security.InvalidKeyException
      // javax.crypto.IllegalBlockSizeException
      // javax.crypto.BadPaddingException
      throw new RuntimeException(e.getMessage(), e);
    }
  }
  /**
   * Parse a DER stream into an X.509 certificate.
   *
   * @param encoded The encoded bytes.
   */
  private void parse(InputStream encoded) throws Exception {
    DERReader der = new DERReader(encoded);

    // Certificate ::= SEQUENCE {
    DERValue cert = der.read();
    debug("start Certificate  len == " + cert.getLength());

    this.encoded = cert.getEncoded();
    if (!cert.isConstructed()) {
      throw new IOException("malformed Certificate");
    }

    // TBSCertificate ::= SEQUENCE {
    DERValue tbsCert = der.read();
    if (tbsCert.getValue() != DER.CONSTRUCTED_VALUE) {
      throw new IOException("malformed TBSCertificate");
    }
    tbsCertBytes = tbsCert.getEncoded();
    debug("start TBSCertificate  len == " + tbsCert.getLength());

    // Version ::= INTEGER [0] { v1(0), v2(1), v3(2) }
    DERValue val = der.read();
    if (val.getTagClass() == DER.CONTEXT && val.getTag() == 0) {
      version = ((BigInteger) der.read().getValue()).intValue() + 1;
      val = der.read();
    } else {
      version = 1;
    }
    debug("read version == " + version);

    // SerialNumber ::= INTEGER
    serialNo = (BigInteger) val.getValue();
    debug("read serial number == " + serialNo);

    // AlgorithmIdentifier ::= SEQUENCE {
    val = der.read();
    if (!val.isConstructed()) {
      throw new IOException("malformed AlgorithmIdentifier");
    }
    int certAlgLen = val.getLength();
    debug("start AlgorithmIdentifier  len == " + certAlgLen);
    val = der.read();

    //   algorithm    OBJECT IDENTIFIER,
    algId = (OID) val.getValue();
    debug("read algorithm ID == " + algId);

    //   parameters   ANY DEFINED BY algorithm OPTIONAL }
    if (certAlgLen > val.getEncodedLength()) {
      val = der.read();
      if (val == null) {
        algVal = null;
      } else {
        algVal = val.getEncoded();
      }
      if (val.isConstructed()) {
        encoded.skip(val.getLength());
      }
      debug("read algorithm parameters == " + algVal);
    }

    // issuer   Name,
    val = der.read();
    issuer = new X500Name(val.getEncoded());
    der.skip(val.getLength());
    debug("read issuer == " + issuer);

    // Validity ::= SEQUENCE {
    //   notBefore   Time,
    //   notAfter    Time }
    if (!der.read().isConstructed()) {
      throw new IOException("malformed Validity");
    }
    notBefore = (Date) der.read().getValue();
    notAfter = (Date) der.read().getValue();
    debug("read notBefore == " + notBefore);
    debug("read notAfter == " + notAfter);

    // subject   Name,
    val = der.read();
    subject = new X500Name(val.getEncoded());
    der.skip(val.getLength());
    debug("read subject == " + subject);

    // SubjectPublicKeyInfo ::= SEQUENCE {
    //   algorithm         AlgorithmIdentifier,
    //   subjectPublicKey  BIT STRING }
    DERValue spki = der.read();
    if (!spki.isConstructed()) {
      throw new IOException("malformed SubjectPublicKeyInfo");
    }
    KeyFactory spkFac = KeyFactory.getInstance("X.509");
    subjectKey = spkFac.generatePublic(new X509EncodedKeySpec(spki.getEncoded()));
    der.skip(spki.getLength());
    debug("read subjectPublicKey == " + subjectKey);

    if (version > 1) {
      val = der.read();
    }
    if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 1) {
      byte[] b = (byte[]) val.getValue();
      issuerUniqueId = new BitString(b, 1, b.length - 1, b[0] & 0xFF);
      debug("read issuerUniqueId == " + issuerUniqueId);
      val = der.read();
    }
    if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 2) {
      byte[] b = (byte[]) val.getValue();
      subjectUniqueId = new BitString(b, 1, b.length - 1, b[0] & 0xFF);
      debug("read subjectUniqueId == " + subjectUniqueId);
      val = der.read();
    }
    if (version >= 3 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 3) {
      val = der.read();
      debug("start Extensions  len == " + val.getLength());
      int len = 0;
      while (len < val.getLength()) {
        DERValue ext = der.read();
        debug("start extension  len == " + ext.getLength());
        Extension e = new Extension(ext.getEncoded());
        extensions.put(e.getOid(), e);
        der.skip(ext.getLength());
        len += ext.getEncodedLength();
        debug("count == " + len);
      }
    }

    val = der.read();
    if (!val.isConstructed()) {
      throw new IOException("malformed AlgorithmIdentifier");
    }
    int sigAlgLen = val.getLength();
    debug("start AlgorithmIdentifier  len == " + sigAlgLen);
    val = der.read();
    sigAlgId = (OID) val.getValue();
    debug("read algorithm id == " + sigAlgId);
    if (sigAlgLen > val.getEncodedLength()) {
      val = der.read();
      if (val.getValue() == null) {
        if (subjectKey instanceof DSAPublicKey) {
          AlgorithmParameters params = AlgorithmParameters.getInstance("DSA");
          DSAParams dsap = ((DSAPublicKey) subjectKey).getParams();
          DSAParameterSpec spec = new DSAParameterSpec(dsap.getP(), dsap.getQ(), dsap.getG());
          params.init(spec);
          sigAlgVal = params.getEncoded();
        }
      } else {
        sigAlgVal = (byte[]) val.getEncoded();
      }
      if (val.isConstructed()) {
        encoded.skip(val.getLength());
      }
      debug("read parameters == " + sigAlgVal);
    }
    signature = ((BitString) der.read().getValue()).toByteArray();
    debug("read signature ==\n" + Util.hexDump(signature, ">>>> "));
  }
  private void run(String mode) throws Exception {

    DHParameterSpec dhSkipParamSpec;

    if (mode.equals("GENERATE_DH_PARAMS")) {
      // Some central authority creates new DH parameters
      System.out.println("Creating Diffie-Hellman parameters (takes VERY long) ...");
      AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator.getInstance("DH");
      paramGen.init(512);
      AlgorithmParameters params = paramGen.generateParameters();
      dhSkipParamSpec = (DHParameterSpec) params.getParameterSpec(DHParameterSpec.class);
    } else {
      // use some pre-generated, default DH parameters
      System.out.println("Using SKIP Diffie-Hellman parameters");
      dhSkipParamSpec = new DHParameterSpec(skip1024Modulus, skip1024Base);
    }

    /*
     * Alice creates her own DH key pair, using the DH parameters from
     * above
     */
    System.out.println("ALICE: Generate DH keypair ...");
    KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");
    aliceKpairGen.initialize(dhSkipParamSpec);
    KeyPair aliceKpair = aliceKpairGen.generateKeyPair();

    // Alice creates and initializes her DH KeyAgreement object
    System.out.println("ALICE: Initialization ...");
    KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
    aliceKeyAgree.init(aliceKpair.getPrivate());

    // Alice encodes her public key, and sends it over to Bob.
    byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded();

    /*
     * Let's turn over to Bob. Bob has received Alice's public key
     * in encoded format.
     * He instantiates a DH public key from the encoded key material.
     */
    KeyFactory bobKeyFac = KeyFactory.getInstance("DH");
    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(alicePubKeyEnc);
    PublicKey alicePubKey = bobKeyFac.generatePublic(x509KeySpec);

    /*
     * Bob gets the DH parameters associated with Alice's public key.
     * He must use the same parameters when he generates his own key
     * pair.
     */
    DHParameterSpec dhParamSpec = ((DHPublicKey) alicePubKey).getParams();

    // Bob creates his own DH key pair
    System.out.println("BOB: Generate DH keypair ...");
    KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
    bobKpairGen.initialize(dhParamSpec);
    KeyPair bobKpair = bobKpairGen.generateKeyPair();

    // Bob creates and initializes his DH KeyAgreement object
    System.out.println("BOB: Initialization ...");
    KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
    bobKeyAgree.init(bobKpair.getPrivate());

    // Bob encodes his public key, and sends it over to Alice.
    byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded();

    /*
     * Alice uses Bob's public key for the first (and only) phase
     * of her version of the DH
     * protocol.
     * Before she can do so, she has to instantiate a DH public key
     * from Bob's encoded key material.
     */
    KeyFactory aliceKeyFac = KeyFactory.getInstance("DH");
    x509KeySpec = new X509EncodedKeySpec(bobPubKeyEnc);
    PublicKey bobPubKey = aliceKeyFac.generatePublic(x509KeySpec);
    System.out.println("ALICE: Execute PHASE1 ...");
    aliceKeyAgree.doPhase(bobPubKey, true);

    /*
     * Bob uses Alice's public key for the first (and only) phase
     * of his version of the DH
     * protocol.
     */
    System.out.println("BOB: Execute PHASE1 ...");
    bobKeyAgree.doPhase(alicePubKey, true);

    /*
     * At this stage, both Alice and Bob have completed the DH key
     * agreement protocol.
     * Both generate the (same) shared secret.
     */
    byte[] aliceSharedSecret = aliceKeyAgree.generateSecret();
    int aliceLen = aliceSharedSecret.length;

    byte[] bobSharedSecret = new byte[aliceLen];
    int bobLen;
    try {
      // show example of what happens if you
      // provide an output buffer that is too short
      bobLen = bobKeyAgree.generateSecret(bobSharedSecret, 1);
    } catch (ShortBufferException e) {
      System.out.println(e.getMessage());
    }
    // provide output buffer of required size
    bobLen = bobKeyAgree.generateSecret(bobSharedSecret, 0);

    System.out.println("Alice secret: " + toHexString(aliceSharedSecret));
    System.out.println("Bob secret: " + toHexString(bobSharedSecret));

    if (!java.util.Arrays.equals(aliceSharedSecret, bobSharedSecret))
      throw new Exception("Shared secrets differ");
    System.out.println("Shared secrets are the same");

    /*
     * Now let's return the shared secret as a SecretKey object
     * and use it for encryption. First, we generate SecretKeys for the
     * "DES" algorithm (based on the raw shared secret data) and
     * then we use DES in ECB mode
     * as the encryption algorithm. DES in ECB mode does not require any
     * parameters.
     *
     * Then we use DES in CBC mode, which requires an initialization
     * vector (IV) parameter. In CBC mode, you need to initialize the
     * Cipher object with an IV, which can be supplied using the
     * javax.crypto.spec.IvParameterSpec class. Note that you have to use
     * the same IV for encryption and decryption: If you use a different
     * IV for decryption than you used for encryption, decryption will
     * fail.
     *
     * NOTE: If you do not specify an IV when you initialize the
     * Cipher object for encryption, the underlying implementation
     * will generate a random one, which you have to retrieve using the
     * javax.crypto.Cipher.getParameters() method, which returns an
     * instance of java.security.AlgorithmParameters. You need to transfer
     * the contents of that object (e.g., in encoded format, obtained via
     * the AlgorithmParameters.getEncoded() method) to the party who will
     * do the decryption. When initializing the Cipher for decryption,
     * the (reinstantiated) AlgorithmParameters object must be passed to
     * the Cipher.init() method.
     */
    System.out.println("Return shared secret as SecretKey object ...");
    // Bob
    // NOTE: The call to bobKeyAgree.generateSecret above reset the key
    // agreement object, so we call doPhase again prior to another
    // generateSecret call
    bobKeyAgree.doPhase(alicePubKey, true);
    SecretKey bobDesKey = bobKeyAgree.generateSecret("DES");

    // Alice
    // NOTE: The call to aliceKeyAgree.generateSecret above reset the key
    // agreement object, so we call doPhase again prior to another
    // generateSecret call
    aliceKeyAgree.doPhase(bobPubKey, true);
    SecretKey aliceDesKey = aliceKeyAgree.generateSecret("DES");

    /*
     * Bob encrypts, using DES in ECB mode
     */
    Cipher bobCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
    bobCipher.init(Cipher.ENCRYPT_MODE, bobDesKey);

    byte[] cleartext = "This is just an example".getBytes();
    byte[] ciphertext = bobCipher.doFinal(cleartext);

    /*
     * Alice decrypts, using DES in ECB mode
     */
    Cipher aliceCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
    aliceCipher.init(Cipher.DECRYPT_MODE, aliceDesKey);
    byte[] recovered = aliceCipher.doFinal(ciphertext);

    if (!java.util.Arrays.equals(cleartext, recovered))
      throw new Exception("DES in CBC mode recovered text is " + "different from cleartext");
    System.out.println("DES in ECB mode recovered text is " + "same as cleartext");

    /*
     * Bob encrypts, using DES in CBC mode
     */
    bobCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    bobCipher.init(Cipher.ENCRYPT_MODE, bobDesKey);

    cleartext = "This is just an example".getBytes();
    ciphertext = bobCipher.doFinal(cleartext);
    // Retrieve the parameter that was used, and transfer it to Alice in
    // encoded format
    byte[] encodedParams = bobCipher.getParameters().getEncoded();

    /*
     * Alice decrypts, using DES in CBC mode
     */
    // Instantiate AlgorithmParameters object from parameter encoding
    // obtained from Bob
    AlgorithmParameters params = AlgorithmParameters.getInstance("DES");
    params.init(encodedParams);
    aliceCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    aliceCipher.init(Cipher.DECRYPT_MODE, aliceDesKey, params);
    recovered = aliceCipher.doFinal(ciphertext);

    if (!java.util.Arrays.equals(cleartext, recovered))
      throw new Exception("DES in CBC mode recovered text is " + "different from cleartext");
    System.out.println("DES in CBC mode recovered text is " + "same as cleartext");
  }