Package ch.ethz.prose

Source Code of ch.ethz.prose.SignedAspect

//
//  This file is part of the prose package.
//
//  The contents of this file are subject to the Mozilla Public 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.mozilla.org/MPL/
//
//  Software distributed under the License is distributed on an "AS IS" basis,
//  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
//  for the specific language governing rights and limitations under the
//  License.
//
//  The Original Code is prose.
//
//  The Initial Developer of the Original Code is Andrei Popovici. Portions
//  created by Andrei Popovici are Copyright (C) 2002 Andrei Popovici.
//  All Rights Reserved.
//
//  Contributor(s):
//  $Id: SignedAspect.java,v 1.3 2008/11/18 11:44:47 anicoara Exp $
//  =====================================================================
//

package ch.ethz.prose;

// used packages
import java.io.FileInputStream;
import java.io.IOException;
import java.rmi.MarshalledObject;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.SignedObject;
import java.util.List;

import ch.ethz.prose.crosscut.Crosscut;
import ch.ethz.inf.util.Logger;

/**
* Class SignedAspect is a wrapper for an Aspect contained in a
* SignedObject. Thus it is possible to verify the signer of the
* extension before it is used. For security reason, this class
* is (and has to be) declared <code>final</code><p>
*
* At construction, the public and private keys passed as <code>
* KeyPair</code> are not checked for being a valid pair
* and the private key is not stored for later use. Only
* an explicit call to <code>verifyExtension</code> does
* check the public key stored. The signing algorithm
* to use is deduced by the algorithm type of the public
* key: if the public key is of type "DSA" then the algorithm
* "SHA1withDSA" is used, in case of an "RSA" key it is "MD5withRSA".
* Keys generated with the <code>keytool</code> for the standard
* Java 2 keystore are of type "DSA" if not specified otherwise.
* The creation of certificates has to be performed by a third party
* tool, such as the ones provided with OpenSSL.<p>
*
* The JCE signing engine that is used can not be specified for the
* moment, this class simply uses the first available one.<p>
*
* To repeat: It is up to the user of this class to assign trust to such
* an extension, this class can only be used to transfer an extension
* secured from unnoticed changes.<p>
*
* Remark: to simplify the security auditing of this class, the
* necessary and constant parameters are passed to the constructor
* and no additional setter-methods are available.
*
* @version  $Revision: 1.3 $
* @author  Marcel Muller
*/
final public class SignedAspect extends Aspect {

  private static final long serialVersionUID = 3256441395777779248L
  private static KeyPair keyPair;

  private SignedObject signedExtension;
  private PublicKey publicKey;
  // private Certificate[] certificateChain; // will work only with jdk 1.3 and later

  transient Aspect wrappedExtension;
  transient boolean verified = false;


  /**
   * Constructs a signed extension and protects it from being modified unnoticed.
   * Only the public key from the key pair passed is store in the generated object.
   *
   * @param extension  the extension to be wrapped into a SignedObject
   * @param keys the key pair used to sign and verify the extension
   */
  public SignedAspect(Aspect extension, KeyPair keys) {
    publicKey = keys.getPublic();

    try {
      Signature signingEngine = Signature.getInstance(getSigningAlgorithm());
      signedExtension = new SignedObject(new MarshalledObject(extension), keys.getPrivate(), signingEngine);
    } catch (Exception e) {
      throw new IllegalArgumentException("failed to sign extension ("+e+")");
    }
  }

  // delegate work
  public void insertionAction(boolean beforeInsertion) throws AspectInsertionException {
    getExtension().insertionAction(beforeInsertion);
  }


  public void withdrawalAction(boolean beforeWithdrawal) {
    getExtension().withdrawalAction(beforeWithdrawal);
  }

  protected Crosscut[] crosscuts() {
    return getExtension().crosscuts();
  }

  public List getCrosscuts() {
    return getExtension().getCrosscuts();
  }

  /**
   * Convinience method to sign extensions. Throws IllegalStateException
   * if signing is not possible.<p>
   *
   * FIX: CONTAINS A LOT OF HARD CODED STUFF!!!!
   */
  public static SignedAspect signExtension(Aspect ext) {
    try {
      if (keyPair == null) {
        String ksl = System.getProperty("ch.ethz.prose.keystore.location");
        String ksp = System.getProperty("ch.ethz.prose.keystore.password");
        String alias = "runes-system"; // FIX

        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(new FileInputStream(ksl), ksp.toCharArray());
        PrivateKey privateKey = (PrivateKey) ks.getKey(alias, alias.toCharArray()); // FIX, password
        PublicKey publicKey = ks.getCertificate(alias).getPublicKey();
        keyPair = new KeyPair(publicKey, privateKey);
      }

      return new SignedAspect(ext, keyPair);

    } catch (Exception e) {
      Logger.error("SignedAspect.signExtension: could not sign extension", e);
      throw new IllegalStateException("could not sign extension");
    }
  }

  /**
   * Verifies that the public key stored in this object corresponds
   * to the private key used to sign the extension.
   *
   * @throws NoSuchAlgorithmException
   * @throws SignatureException
   * @throws InvalidKeyException
   */
  public void verifyExtension() throws NoSuchAlgorithmException, SignatureException, InvalidKeyException {
    Signature verificationEngine = Signature.getInstance(getSigningAlgorithm());
    signedExtension.verify(publicKey, verificationEngine);
    verified = true;
  }

  /**
   * Returns wrapped extension without checking it for being signed
   * by a key corresponding to the public key stored.
   *
   * @return the wrapped extension
   */
  public Aspect getExtension() {
    try {
      if (wrappedExtension == null) {
        wrappedExtension = (Aspect) ((MarshalledObject) signedExtension.getObject()).get();
      }

      return wrappedExtension;

    } catch (IOException e) {
      Logger.error("SignedAspect.getExtension: io exception", e);
      throw new RuntimeException("contained exception " + e);

    } catch (ClassNotFoundException e) {
      Logger.error("SignedAspect.getExtension: class not found", e);
      throw new RuntimeException("contained exception " + e);
    }
  }

  /**
   * Returns public key that possibly corresponds to signing key
   *
   * @return the public key passed in the constructor
   */
  public PublicKey getPublicKey() {
    return publicKey;
  }

  /**
   * Returns signing algorithm name
   *
   * @return the algorithm name
   */
  public String getSigningAlgorithm() {
    String signingAlgorithm;

    if (publicKey.getAlgorithm().equals("DSA")) {
      signingAlgorithm = "SHA1withDSA";

    } else if (publicKey.getAlgorithm().equals("RSA")) {
      signingAlgorithm = "MD5withRSA";

    } else {
      throw new IllegalArgumentException("unknown key algorithm, currently supported are DSA and RSA");
    }

    return signingAlgorithm;
  }

  /**
   * Implementation: we don't use getExtension() here, as we don't want to
   * de-marshall extension just because of the toString call
   */
  public String toString() {
    if (wrappedExtension != null) {
      return "SignedAspect, "+ (verified?"verified":"not verified") +", containing " + wrappedExtension.toString();

    } else {
      return "SignedAspect, not accessed";
    }
  }

  //public void setCertificateChain(Certificate[] certificateChain) {
  //    this.certificateChain = certificateChain;
  //}

  //public Certificate[] getCertificateChain() {
  //     return certificateChain;
  //}


  /**
   * Delegate to wrapped extension
   */
  public boolean equals(Object o) {
    if (o instanceof SignedAspect) {
      return getExtension().equals(((SignedAspect) o).getExtension());

    } else if (o instanceof Aspect) {
      return getExtension().equals(o);

    } else {
      return false;
    }
  }

  /**
   * Delegate to wrapped extension
   */
  public int hashCode() {
    return getExtension().hashCode();
  }
}
TOP

Related Classes of ch.ethz.prose.SignedAspect

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.