com.licel.jcardsim.crypto.KeyPairImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcardsim Show documentation
Show all versions of jcardsim Show documentation
jCardSim is open-source library contains implementation of Java Card API
The newest version!
/*
* Copyright 2011 Licel LLC.
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.licel.jcardsim.crypto;
import java.math.BigInteger;
import java.security.SecureRandom;
import javacard.security.CryptoException;
import javacard.security.KeyBuilder;
import javacard.security.KeyPair;
import javacard.security.PrivateKey;
import javacard.security.PublicKey;
import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
import org.bouncycastle.crypto.KeyGenerationParameters;
import org.bouncycastle.crypto.generators.DSAKeyPairGenerator;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.DSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.DSAKeyParameters;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
import org.bouncycastle.crypto.params.DSAValidationParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECKeyParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
/**
* Implementation
* KeyPair
based on BouncyCastle CryptoAPI
*
* @see KeyPair
* @see RSAKeyPairGenerator
* @see DSAKeyPairGenerator
* @see ECKeyPairGenerator
*/
public final class KeyPairImpl {
byte algorithm;
short keyLength;
AsymmetricCipherKeyPairGenerator engine;
PrivateKey privateKey;
PublicKey publicKey;
SecureRandom rnd = new SecureRandom();
KeyGenerationParameters keyGenerationParameters;
/**
* (Re)Initializes the key objects encapsulated in this
* KeyPair
instance with new key values. The initialized public
* and private key objects encapsulated in this instance will then be
* suitable for use with the
* Signature
,
* Cipher
and
* KeyAgreement
objects. An internal secure random number
* generator is used during new key pair generation. Notes:
* - For the RSA algorithm, if the exponent value in the public key
* object is pre-initialized, it will be retained. Otherwise, a default
* value of 65537 will be used.
- For the DSA algorithm, if the
* p, q and g parameters of the public key object are pre-initialized, they
* will be retained. Otherwise, default precomputed parameter sets will be
* used. The required default precomputed values are listed in Appendix
* B of Java Cryptography Architecture API Specification &
* Reference document.
- For the EC case, if the Field, A, B,
* G and R parameters of the key pair are pre-initialized, then they will be
* retained. Otherwise default pre-specified values MAY be used (e.g. WAP
* predefined curves), since computation of random generic EC keys is
* infeasible on the smart card platform.
- If the time taken to
* generate the key values is excessive, the implementation may
* automatically request additional APDU processing time from the CAD.
*
*
* @throws CryptoException with the following reason codes:
* CryptoException.ILLEGAL_VALUE
if the exponent value
* parameter in RSA or the p, q, g parameter set in DSA or the Field, A, B,
* G and R parameter set in EC is invalid.
* @see APDU
* @see Signature
* @see Cipher
* @see RSAPublicKey
* @see ECKey
* @see DSAKey
*/
public final void genKeyPair()
throws CryptoException {
initEngine();
AsymmetricCipherKeyPair kp = engine.generateKeyPair();
// rsa
if (kp.getPublic() instanceof RSAKeyParameters) {
publicKey = new RSAKeyImpl((RSAKeyParameters) kp.getPublic());
if (kp.getPrivate() instanceof RSAPrivateCrtKeyParameters) {
privateKey = new RSAPrivateCrtKeyImpl((RSAPrivateCrtKeyParameters) kp.getPrivate());
} else if (kp.getPrivate() instanceof RSAKeyParameters) {
privateKey = new RSAKeyImpl((RSAKeyParameters) kp.getPrivate());
}
} else // dsa
if (kp.getPublic() instanceof DSAPublicKeyParameters) {
publicKey = new DSAPublicKeyImpl((DSAPublicKeyParameters) kp.getPublic());
privateKey = new DSAPrivateKeyImpl((DSAPrivateKeyParameters) kp.getPrivate());
} else // ecc
if (kp.getPublic() instanceof ECPublicKeyParameters) {
publicKey = new ECPublicKeyImpl((ECPublicKeyParameters) kp.getPublic());
privateKey = new ECPrivateKeyImpl((ECPrivateKeyParameters) kp.getPrivate());
} else {
CryptoException.throwIt(CryptoException.ILLEGAL_USE);
}
}
/**
* Constructs a
* KeyPair
instance for the specified algorithm and keylength;
* the encapsulated keys are uninitialized. To initialize the
* KeyPair
instance use the
* genKeyPair()
method. The encapsulated key objects are of
* the specified
* keyLength
size and implement the appropriate
* Key
interface associated with the specified algorithm
* (example -
* RSAPublicKey
interface for the public key and
* RSAPrivateKey
interface for the private key within an
* ALG_RSA
key pair).
Notes:
- The key objects
* encapsulated in the generated
KeyPair
object need
* not support the KeyEncryption
interface.
*
* @param algorithm the type of algorithm whose key pair needs to be
* generated. Valid codes listed in ALG_..
constants above.
* {@link KeyPair}
* @param keyLength the key size in bits. The valid key bit lengths are key
* type dependent. See the KeyBuilder
class.
* @see KeyBuilder
* @throws CryptoException with the following reason codes:
* CryptoException.NO_SUCH_ALGORITHM
if the requested
* algorithm associated with the specified type, size of key is not
* supported.
* @see KeyBuilder
* @see Signature
* @see KeyEncryption
* @see Cipher
*/
public KeyPairImpl(byte algorithm, short keyLength)
throws CryptoException {
this.algorithm = algorithm;
this.keyLength = keyLength;
}
/**
* Constructs a new
* KeyPair
object containing the specified public key and
* private key. Note that this constructor only stores references to the
* public and private key components in the generated
* KeyPair
object. It does not throw an exception if the key
* parameter objects are uninitialized.
*
* @param publicKey the public key.
* @param privateKey the private key.
* @throws CryptoException with the following reason codes:
* CryptoException.ILLEGAL_VALUE
if the input parameter key
* objects are inconsistent with each other - i.e mismatched algorithm, size
* etc. CryptoException.NO_SUCH_ALGORITHM
if the algorithm
* associated with the specified type, size of key is not supported.
*/
public KeyPairImpl(PublicKey publicKey, PrivateKey privateKey)
throws CryptoException {
if (publicKey == null && privateKey == null) {
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
if ((publicKey != null) && !(publicKey instanceof KeyWithParameters)) {
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
this.publicKey = publicKey;
if (this.publicKey != null) {
selectAlgorithmByType(this.publicKey.getType());
}
if ((privateKey != null) && !(privateKey instanceof KeyWithParameters)) {
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
this.privateKey = privateKey;
if (this.privateKey != null) {
selectAlgorithmByType(this.privateKey.getType());
}
}
/**
* Returns a reference to the public key component of this
* KeyPair
object.
*
* @return a reference to the public key.
*/
public PublicKey getPublic() {
return publicKey;
}
/**
* Returns a reference to the private key component of this
* KeyPair
object.
*
* @return a reference to the private key.
*/
public PrivateKey getPrivate() {
return privateKey;
}
private void selectAlgorithmByType(byte keyType) {
switch (keyType) {
case KeyBuilder.TYPE_RSA_PRIVATE:
case KeyBuilder.TYPE_RSA_PUBLIC:
algorithm = KeyPair.ALG_RSA;
break;
case KeyBuilder.TYPE_RSA_CRT_PRIVATE:
algorithm = KeyPair.ALG_RSA_CRT;
break;
case KeyBuilder.TYPE_EC_F2M_PUBLIC:
case KeyBuilder.TYPE_EC_F2M_PRIVATE:
algorithm = KeyPair.ALG_EC_F2M;
break;
case KeyBuilder.TYPE_EC_FP_PUBLIC:
case KeyBuilder.TYPE_EC_FP_PRIVATE:
algorithm = KeyPair.ALG_EC_FP;
break;
case KeyBuilder.TYPE_DSA_PUBLIC:
case KeyBuilder.TYPE_DSA_PRIVATE:
algorithm = KeyPair.ALG_DSA;
break;
}
}
/**
* Init key pair generation engine
*/
private void initEngine() {
if (publicKey != null || privateKey != null) {
keyGenerationParameters = ((KeyImpl) (privateKey == null ? publicKey : privateKey)).getKeyGenerationParameters(rnd);
}
switch (algorithm) {
case KeyPair.ALG_RSA:
case KeyPair.ALG_RSA_CRT:
if (keyGenerationParameters == null) {
keyGenerationParameters = RSAKeyImpl.getDefaultKeyGenerationParameters(keyLength, rnd);
}
engine = new RSAKeyPairGenerator();
break;
//
case KeyPair.ALG_DSA:
if (keyLength < 512 || keyLength > 1024 || keyLength % 64 != 0) {
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
if (keyGenerationParameters == null) {
keyGenerationParameters = DSAKeyImpl.getDefaultKeyGenerationParameters(keyLength, rnd);
}
engine = new DSAKeyPairGenerator();
break;
// ecc
case KeyPair.ALG_EC_F2M:
case KeyPair.ALG_EC_FP:
if (keyGenerationParameters == null) {
keyGenerationParameters = ECKeyImpl.getDefaultKeyGenerationParameters(algorithm, keyLength, rnd);
}
engine = new ECKeyPairGenerator();
break;
default:
CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM);
break;
}
engine.init(keyGenerationParameters);
}
}