Home > Products > Communication & Messaging Security > iSaSiLk > documentation > security provider
Home > Products > Communication & Messaging Security > iSaSiLk > documentation > security provider




























iSaSiLk makes use of the JCA/JCE API for all cryptographic operations.
However, it does not use the
getInstance()
methods of those
API classes directly, rather it uses a SecurityProvider class which
centralizes all the various calls. Basically, there are two reasons for
that. First, there is is no portable way to perform all
required operations. For example, there is no provider indepedent way
to construct a Principal object from its DER encoding. Also, some providers do
not implement all required features defined in JCA/JCE.
The second reason is that the SecurityProvider concept allows for more flexibility
and makes it easier to use several providers at the same time.
The important class here is
iaik.security.ssl.SecurityProvider
.
It contains all the relevant API methods and provides a default
SecurityProvider implementation that can be customized to accommodate your needs.
Additionally it contains the static setting
of the currently active SecurityProvider. It can be set and inspected using
the methods
setSecurityProvider()
and
getSecurityProvider()
,
respectively. Note that this is a global setting for the entire VM.
The SecurityProvider class defines a number of constant strings as well
as methods.
Constant strings are defined using the following variable names:
ALG_DIGEST_MD5 ALG_DIGEST_SHA ALG_HMAC_MD5 ALG_HMAC_SHA ALG_SIGNATURE_SHADSA ALG_SIGNATURE_RAWDSA ALG_SIGNATURE_MD5RSA ALG_KEYPAIR_RSA ALG_KEYEX_RSA ALG_KEYEX_DSA ALG_KEYEX_DSA_CLIENT ALG_KEYEX_DH ALG_KEYEX_PSK ALG_KEYEX_DHE_PSK ALG_KEYEX_RSA_PSK ALG_CIPHER_AES ALG_CIPHER_AES_PKCS5 ALG_CIPHER_RC4 ALG_CIPHER_RC2 ALG_CIPHER_DES ALG_CIPHER_3DES ALG_CIPHER_IDEA ALG_CIPHER_AES ALG_CIPHER_RSA ALG_CIPHER_RSA_SIGN ALG_CIPHER_RSA_VERIFY ALG_CIPHER_RSA_ENCRYPT ALG_CIPHER_RSA_DECRYPT ALG_CIPHER_RSA_ENCRYPT_SSL2
They are used with the respective
getInstance()
methods.
A special case are the
ALG_CIPHER_RSA_xxx
strings. They are
used to simplify differentiation between the various types of RSA
operations, which is useful particularly for Smartcards (see also
iSaSiLk and Smartcards
).
Usually the same RSA implementation is used in all cases though.
The SecurityProvider class has two constructors. A no-argument constructor,
which will create a security provider that searches all JCA installed
providers, and a constructor that takes as string argument the name of
the only provider to be searched. This is usefull when you want to avoid
that implementations from some other provider is used.
The security provider defines the following methods, all of which
have been implemented to work in a provider independent way using
only the JCA/JCE APIs. Note that does not necessarily mean that
they will work with any provider as some providers do not implement
the necessary KeyFactories, etc.
Note that the
getCipher()
,
getSignature()
, and
getMac()
must
initialize the respective
object before returning it if requested (i.e. mode is not SIGNATURE_NONE,
CIPHER_NONE, key is not null, respectively). This structure was chosen to
allow you to convert keys if your provider can only handle its own keys objects, etc.
For example, for symmetric keys the
SecretKeySpec
class is used,
which may not be supported by all providers.
The following two methods could not be implemented in a provider independent way and only
return
null
when called. For this particular case the library has been
designed to work without them as well, but note that this disables the more
precise client authentication certificate selection. Therefore, it is recommended
to provide concrete implementations for your provider if possible.
The following method could not be implemented in a provider independent way and only
return
null
when called. For this particular case the library has been
designed to work without them as well, but note that this disables the more
precise server name verification. Therefore, it is recommended
to provide concrete implementations for your provider if possible.
The following methods could not be implemented in a provider independent way.
They are required when using iSaSiLk with TLS extensions:
Below we provide the source code for the SecurityProvider class.
It is the code from iSaSiLk slightly modified
(comments and constant strings removed, etc.).
protected String providerName;
public SecurityProvider() { this(null); }
public SecurityProvider(String providerName) { this.providerName = providerName; }
protected DHPublicKey getDHPublicKey(BigInteger y, BigInteger p, BigInteger g) throws Exception { DHPublicKeySpec spec = new DHPublicKeySpec(y, p, g); KeyFactory factory = (providerName == null) ? KeyFactory.getInstance("DH") : KeyFactory.getInstance("DH", providerName); DHPublicKey key = (DHPublicKey)factory.generatePublic(spec); return key; }
protected DHPrivateKey getDHPrivateKey(BigInteger x, BigInteger p, BigInteger g) throws Exception { DHPrivateKeySpec spec = new DHPrivateKeySpec(x, p, g); KeyFactory factory = (providerName == null) ? KeyFactory.getInstance("DH") : KeyFactory.getInstance("DH", providerName); DHPrivateKey key = (DHPrivateKey)factory.generatePrivate(spec); return key; }
protected RSAPublicKey getRSAPublicKey(BigInteger modulus, BigInteger publicExponent) throws Exception { RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, publicExponent); KeyFactory factory = (providerName == null) ? KeyFactory.getInstance("RSA") : KeyFactory.getInstance("RSA", providerName); RSAPublicKey key = (RSAPublicKey)factory.generatePublic(spec); return key; }
protected X509Certificate getX509Certificate(byte[] array) throws Exception { CertificateFactory factory = (providerName == null) ? CertificateFactory.getInstance("X.509") : CertificateFactory.getInstance("X.509", providerName); InputStream in = new ByteArrayInputStream(array); X509Certificate cert = (X509Certificate)factory.generateCertificate(in); return cert; }
protected Principal getPrincipal(byte[] array) throws Exception { return null; }
protected byte[] getEncodedPrincipal(Principal principal) { return null; }
protected MessageDigest getMessageDigest(String algorithm) throws Exception { return (providerName == null) ? MessageDigest.getInstance(algorithm) : MessageDigest.getInstance(algorithm, providerName); }
protected Mac getMac(String algorithm, Key key) throws Exception { Mac mac = (providerName == null) ? Mac.getInstance(algorithm) : Mac.getInstance(algorithm, providerName); if( key != null ) { mac.init(key); } return mac; }
protected Signature getSignature(String algorithm, int mode, Key key, SecureRandom random) throws Exception { Signature sig = (providerName == null) ? Signature.getInstance(algorithm) : Signature.getInstance(algorithm, providerName); if( mode == SIGNATURE_SIGN ) { sig.initSign((PrivateKey)key); } else if( mode == SIGNATURE_VERIFY ) { sig.initVerify((PublicKey)key); } // do nothing for SIGNATURE_NONE return sig; }
protected byte[] calculateRawSignature(String algorithmName, byte[] dataToBeSigned, PrivateKey key, SecureRandom random) throws Exception { Cipher cipher = getCipher(algorithmName, CIPHER_ENCRYPT, key, null, random); byte[] signature = cipher.doFinal(dataToBeSigned); return signature ; }
protected boolean verifyRawSignature(String algorithmName, byte[] dataToBeSigned, byte[] signature, PublicKey key) throws Exception { Cipher cipher = getCipher(algorithmName, CIPHER_DECRYPT, key, null, null); byte[] received_hash = cipher.doFinal(signature); return Utils.equalsBlock(dataToBeSigned, received_hash); }
protected Cipher getCipher(String algorithm, int mode, Key key, AlgorithmParameterSpec spec, SecureRandom random) throws Exception { if( algorithm.startsWith(ALG_CIPHER_RSA) ) { algorithm = ALG_CIPHER_RSA; } Cipher cipher = (providerName == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, providerName); if( mode != CIPHER_NONE ) { int cmode = (mode == CIPHER_ENCRYPT) ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE; cipher.init(cmode, key, spec, random); } return cipher; }
protected KeyPairGenerator getKeyPairGenerator(String algorithm) throws Exception { return (providerName == null) ? KeyPairGenerator.getInstance(algorithm) : KeyPairGenerator.getInstance(algorithm, providerName); }
protected SecureRandom getSecureRandom() { return new SecureRandom(); }
protected String[] getTLSServerName(X509Certificate serverCert) { return null; }
Basically there are two scenarios:
In the first case the easiest thing to do is to subclass the
IaikProvider
class. For example,
public class MySecurityProvider extends IaikProvider {
protected Cipher getCipher(String algorithm, int mode, Key key, AlgorithmParameterSpec param, SecureRandom random) throws Exception { if (key instanceof IAIKPKCS11Key) { if (algorithm.startsWith(ALG_CIPHER_RSA)) { algorithm = ALG_CIPHER_RSA; } cipherEngine = Cipher.getInstance(algorithm, ((IAIKPKCS11Key) key).getTokenManager().getProvider().getName()); if (mode != CIPHER_NONE) { int cmode = (mode == CIPHER_ENCRYPT) ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE; cipherEngine.init(cmode, key, param, random); } } else { cipherEngine = super.getCipher(algorithm, mode, key, param, random); }
} }
In the second case, i.e. you want to use a different provider altogether
and not use the IAIK JCE at all (for whatever reason ;-) it will be easiest
to start with the
SecurityProvider
class and override those
methods where you cannot use the default implementation. It might we
wise to have the IAIK JCE in your
CLASSPATH
at first so that
you can use its implementations for those parts you have not changed
to use your provider yet.
To use your own SecurityProvider in your application you only have
to make sure you have all required classes in your
CLASSPATH
and that you activate it at the beginning of your program. This
can be done using, for example:
Alternatively you may set your security provider via property file. iSaSiLk
first looks if there is a property file with name "SecurityProvider.properties"
located in package iaik.security.ssl. You may set the value of the only "class"
entry to the full name of your provider, e.g.:
Of course you also have to make sure your provider is initialized
in whatever way(s) it requires, e.g. add it as a JCE security provider.
