/***********************************************************
* $Id: PKCS11PrivateKey.java 44 2007-01-28 20:29:17Z wolfgang.glas $
*
* PKCS11 provider of the OpenSC project http://www.opensc-project.org
*
* Copyright (C) 2002-2006 ev-i Informationstechnologie GmbH
*
* Created: Jul 21, 2006
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
***********************************************************/
package org.opensc.pkcs11.wrap;
import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.List;
import org.opensc.util.PKCS11Id;
/**
* @author wglas
*
* This class represents a private key stored on a hardware token.
*/
public class PKCS11PrivateKey extends PKCS11Key implements PrivateKey
{
/**
* To be changed upon class layout change.
*/
private static final long serialVersionUID = 930054758668115904L;
boolean extractable;
boolean sensitive;
/**
* @param session The session to which this key belongs.
* @param handle The handle as returned by @see PKCS11Object#enumRawObjects(PKCS11Session, int).
* @throws PKCS11Exception
*/
protected PKCS11PrivateKey(PKCS11Session session, int type, boolean extractable, long handle)
throws PKCS11Exception
{
super(session,type,handle);
this.extractable = extractable;
this.sensitive = super.getBooleanAttribute(PKCS11Attribute.CKA_SENSITIVE);
}
private static PKCS11PrivateKey makePrivateKey(PKCS11Session session, long handle, int keyType, boolean extractable) throws PKCS11Exception
{
//
// Well the rationale behind all this code below is, that we
// have to export non-extractable keys as a plain PrivateKey
// implementation, because the interfaces {RSA,DSA}PrivateKey
// grant access to all private information of the private key.
//
// Moreover, the delayed provider selection described in
// http://java.sun.com/j2se/1.5.0/docs/guide/security/p11guide.html
// come to the end, that implementations of {RSA,DSA}PrivateKey
// are supported by the SunRSA provider, which causes the signature to
// fail lateron, because the the private informations are null.
// (e.g. RSAPrivateKey.getPrivateExponent() == null).
//
// This would render the private keys unusable for SSL peer
// authentication, so this is another argument for exporting a
// non-extractable key as an implementation of the plain PrivateKey
// interface.
//
switch (keyType)
{
case CKK_RSA:
if (extractable)
return new PKCS11RSAPrivateKey(session,handle);
else
return new PKCS11NeRSAPrivateKey(session,handle);
case CKK_DSA:
if (extractable)
return new PKCS11DSAPrivateKey(session,handle);
else
return new PKCS11NeDSAPrivateKey(session,handle);
default:
return new PKCS11PrivateKey(session,keyType,extractable, handle);
}
}
/**
* Fetches all private keys stored in the specified slot.
*
* @param session The session of which to find the certificates.
* @return The list of all private keys found in this slot.
* @throws PKCS11Exception Upon errors from the underlying PKCS11 module.
*/
public static List<PKCS11PrivateKey> getPrivateKeys(PKCS11Session session) throws PKCS11Exception
{
long[] handles = enumRawObjects(session,PKCS11Object.CKO_PRIVATE_KEY);
List<PKCS11PrivateKey> ret = new ArrayList<PKCS11PrivateKey>(handles.length);
for (int i = 0; i < handles.length; i++)
{
int keyType =
PKCS11Object.getULongAttribute(session,handles[i],PKCS11Attribute.CKA_KEY_TYPE);
boolean extractable=
PKCS11Object.getBooleanAttribute(session,handles[i],PKCS11Attribute.CKA_EXTRACTABLE);
PKCS11PrivateKey key= makePrivateKey(session, handles[i], keyType, extractable);
ret.add(key);
}
return ret;
}
/**
* Get the private key with the given id from the session.
*
* @param session The session of which to find a private key.
* @param id The Id of the key to be searched.
* @return The private key with the given id.
* @throws PKCS11Exception Upon error on the underlying PKCS11 module or
* when the key could not be found.
*/
public static PKCS11PrivateKey findPrivateKey(PKCS11Session session, PKCS11Id id) throws PKCS11Exception
{
long handle = findRawObject(session, PKCS11Object.CKO_PRIVATE_KEY, id);
int keyType = PKCS11Object.getULongAttribute(session,handle,PKCS11Attribute.CKA_KEY_TYPE);
boolean extractable=
PKCS11Object.getBooleanAttribute(session,handle,PKCS11Attribute.CKA_EXTRACTABLE);
return makePrivateKey(session,handle,keyType,extractable);
}
/**
* @return The matching public key, if it is stored on the token.
* @throws PKCS11Exception upon errors of the underlying PKCS#11 module or when
* the crresponding public key could not be found on the token.
*/
public PKCS11PublicKey getPublicKey() throws PKCS11Exception
{
return PKCS11PublicKey.findPublicKey((PKCS11Session)this.getParent(), this.getId());
}
/* (non-Javadoc)
* @see org.opensc.pkcs11.wrap.PKCS11Key#getFormat()
*/
@Override
public String getFormat()
{
return null;
}
/**
* @return Returns whether the key is extractable.
*/
public boolean isExtractable()
{
return this.extractable;
}
/**
* @return Returns whether the key is extractable.
*/
public boolean isSensitive()
{
return this.sensitive;
}
}