/** @inheritDoc */
  protected void engineInitVerify(Key publicKey) throws XMLSignatureException {
    if (!(publicKey instanceof PublicKey)) {
      String supplied = publicKey.getClass().getName();
      String needed = PublicKey.class.getName();
      Object exArgs[] = {supplied, needed};

      throw new XMLSignatureException("algorithms.WrongKeyForThisOperation", exArgs);
    }

    try {
      this.signatureAlgorithm.initVerify((PublicKey) publicKey);
    } catch (InvalidKeyException ex) {
      // reinstantiate Signature object to work around bug in JDK
      // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
      Signature sig = this.signatureAlgorithm;
      try {
        this.signatureAlgorithm = Signature.getInstance(signatureAlgorithm.getAlgorithm());
      } catch (Exception e) {
        // this shouldn't occur, but if it does, restore previous
        // Signature
        if (log.isLoggable(java.util.logging.Level.FINE)) {
          log.log(java.util.logging.Level.FINE, "Exception when reinstantiating Signature:" + e);
        }
        this.signatureAlgorithm = sig;
      }
      throw new XMLSignatureException("empty", ex);
    }
  }
  /**
   * Converts, if possible, a given key into a key specification. Currently, the following key
   * specifications are supported:
   *
   * <ul>
   *   <li>for McElieceCCA2PublicKey: {@link X509EncodedKeySpec}, {@link McElieceCCA2PublicKeySpec}
   *   <li>for McElieceCCA2PrivateKey: {@link PKCS8EncodedKeySpec}, {@link
   *       McElieceCCA2PrivateKeySpec}.
   * </ul>
   *
   * @param key the key
   * @param keySpec the key specification
   * @return the specification of the McEliece CCA2 key
   * @throws InvalidKeySpecException if the key type or the key specification is not supported.
   * @see BCMcElieceCCA2PrivateKey
   * @see McElieceCCA2PrivateKeySpec
   * @see BCMcElieceCCA2PublicKey
   * @see McElieceCCA2PublicKeySpec
   */
  public KeySpec getKeySpec(Key key, Class keySpec) throws InvalidKeySpecException {
    if (key instanceof BCMcElieceCCA2PrivateKey) {
      if (PKCS8EncodedKeySpec.class.isAssignableFrom(keySpec)) {
        return new PKCS8EncodedKeySpec(key.getEncoded());
      } else if (McElieceCCA2PrivateKeySpec.class.isAssignableFrom(keySpec)) {
        BCMcElieceCCA2PrivateKey privKey = (BCMcElieceCCA2PrivateKey) key;
        return new McElieceCCA2PrivateKeySpec(
            OID,
            privKey.getN(),
            privKey.getK(),
            privKey.getField(),
            privKey.getGoppaPoly(),
            privKey.getP(),
            privKey.getH(),
            privKey.getQInv());
      }
    } else if (key instanceof BCMcElieceCCA2PublicKey) {
      if (X509EncodedKeySpec.class.isAssignableFrom(keySpec)) {
        return new X509EncodedKeySpec(key.getEncoded());
      } else if (McElieceCCA2PublicKeySpec.class.isAssignableFrom(keySpec)) {
        BCMcElieceCCA2PublicKey pubKey = (BCMcElieceCCA2PublicKey) key;
        return new McElieceCCA2PublicKeySpec(OID, pubKey.getN(), pubKey.getT(), pubKey.getG());
      }
    } else {
      throw new InvalidKeySpecException("Unsupported key type: " + key.getClass() + ".");
    }

    throw new InvalidKeySpecException("Unknown key specification: " + keySpec + ".");
  }
  /** @inheritDoc */
  protected void engineInitSign(Key privateKey) throws XMLSignatureException {
    if (!(privateKey instanceof PrivateKey)) {
      String supplied = privateKey.getClass().getName();
      String needed = PrivateKey.class.getName();
      Object exArgs[] = {supplied, needed};

      throw new XMLSignatureException("algorithms.WrongKeyForThisOperation", exArgs);
    }

    try {
      this.signatureAlgorithm.initSign((PrivateKey) privateKey);
    } catch (InvalidKeyException ex) {
      throw new XMLSignatureException("empty", ex);
    }
  }