jdnssec-tools/src/com/verisignlabs/dnssec/security/DnsKeyAlgorithm.java

292 lines
8.2 KiB
Java
Raw Normal View History

/*
* $Id$
*
* Copyright (c) 2006 VeriSign. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. The name of the author may not
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.verisignlabs.dnssec.security;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.spec.RSAKeyGenParameterSpec;
import java.util.HashMap;
import java.util.logging.Logger;
import org.xbill.DNS.DNSSEC;
/**
* This class handles translated DNS signing algorithm identifiers into
* various usable java implementations.
*
* Besides centralizing the logic surrounding matching a DNSKEY algorithm
* identifier with various crypto implementations, it also handles algorithm
* aliasing -- that is, defining a new algorithm identifier to be equivalent
* to an existing identifier.
*
* @author David Blacka (orig)
* @author $Author: davidb $ (latest)
* @version $Revision: 2098 $
*/
public class DnsKeyAlgorithm
{
public static final int UNKNOWN = -1;
public static final int RSA = 1;
public static final int DH = 2;
public static final int DSA = 3;
private static class Entry
{
public String sigName;
public int baseType;
public Entry(String sigName, int baseType)
{
this.sigName = sigName;
this.baseType = baseType;
}
}
/**
* This is a mapping of algorithm identifier to Entry. The Entry contains
* the data needed to map the algorithm to the various crypto
* implementations.
*/
private HashMap mAlgorithmMap;
/**
* This is a mapping of algorithm mnemonics to algorithm identifiers.
*/
private HashMap mMnemonicToIdMap;
/**
* This is a mapping of identifiers to preferred mnemonic -- the preferred
* one is the first defined one
*/
private HashMap mIdToMnemonicMap;
/** This is a cached key pair generator for RSA keys. */
private KeyPairGenerator mRSAKeyGenerator;
/** This is a cache key pair generator for DSA keys. */
private KeyPairGenerator mDSAKeyGenerator;
private Logger log = Logger.getLogger(this.getClass()
.toString());
/** This is the global instance for this class. */
private static DnsKeyAlgorithm mInstance = null;
public DnsKeyAlgorithm()
{
mAlgorithmMap = new HashMap();
mMnemonicToIdMap = new HashMap();
mIdToMnemonicMap = new HashMap();
// Load the standard DNSSEC algorithms.
addAlgorithm(DNSSEC.RSAMD5, new Entry("MD5withRSA", RSA));
addMnemonic("RSAMD5", DNSSEC.RSAMD5);
addAlgorithm(DNSSEC.DH, new Entry("", DH));
addMnemonic("DH", DNSSEC.DH);
addAlgorithm(DNSSEC.DSA, new Entry("SHA1withDSA", DSA));
addMnemonic("DSA", DNSSEC.DSA);
addAlgorithm(DNSSEC.RSASHA1, new Entry("SHA1withRSA", RSA));
addMnemonic("RSASHA1", DNSSEC.RSASHA1);
addMnemonic("RSA", DNSSEC.RSASHA1);
}
private void addAlgorithm(int algorithm, Entry entry)
{
Integer a = new Integer(algorithm);
mAlgorithmMap.put(a, entry);
}
private void addMnemonic(String m, int alg)
{
Integer a = new Integer(alg);
mMnemonicToIdMap.put(m.toUpperCase(), a);
if (! mIdToMnemonicMap.containsKey(a))
{
mIdToMnemonicMap.put(a, m);
}
}
public void addAlias(int alias, String mnemonic, int original_algorithm)
{
Integer a = new Integer(alias);
Integer o = new Integer(original_algorithm);
if (mAlgorithmMap.containsKey(a))
{
log.warning("Unable to alias algorithm " + alias
+ " because it already exists.");
return;
}
if (!mAlgorithmMap.containsKey(o))
{
log.warning("Unable to alias algorith " + alias
+ " to unknown algorithm identifier " + original_algorithm);
return;
}
mAlgorithmMap.put(a, mAlgorithmMap.get(o));
if (mnemonic != null)
{
addMnemonic(mnemonic, alias);
}
}
private Entry getEntry(int alg)
{
return (Entry) mAlgorithmMap.get(new Integer(alg));
}
public Signature getSignature(int algorithm)
{
Entry entry = getEntry(algorithm);
if (entry == null) return null;
Signature s = null;
try
{
s = Signature.getInstance(entry.sigName);
}
catch (NoSuchAlgorithmException e)
{
log.severe("Unable to get signature implementation for algorithm "
+ algorithm + ": " + e);
}
return s;
}
public int stringToAlgorithm(String s)
{
Integer alg = (Integer) mMnemonicToIdMap.get(s.toUpperCase());
if (alg != null) return alg.intValue();
return -1;
}
public String algToString(int algorithm)
{
return (String) mIdToMnemonicMap.get(new Integer(algorithm));
}
public int baseType(int algorithm)
{
Entry entry = getEntry(algorithm);
if (entry != null) return entry.baseType;
return UNKNOWN;
}
public int standardAlgorithm(int algorithm)
{
switch (baseType(algorithm))
{
case RSA :
return DNSSEC.RSASHA1;
case DSA :
return DNSSEC.DSA;
case DH :
return DNSSEC.DH;
default :
return UNKNOWN;
}
}
public boolean isDSA(int algorithm)
{
return (baseType(algorithm) == DSA);
}
public KeyPair generateKeyPair(int algorithm, int keysize, boolean useLargeExp)
throws NoSuchAlgorithmException
{
KeyPair pair = null;
switch (baseType(algorithm))
{
case RSA :
if (mRSAKeyGenerator == null)
{
mRSAKeyGenerator = KeyPairGenerator.getInstance("RSA");
}
RSAKeyGenParameterSpec rsa_spec;
if (useLargeExp)
{
rsa_spec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F4);
}
else
{
rsa_spec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F0);
}
try
{
mRSAKeyGenerator.initialize(rsa_spec);
}
catch (InvalidAlgorithmParameterException e)
{
// Fold the InvalidAlgorithmParameterException into our existing
// thrown exception. Ugly, but requires less code change.
throw new NoSuchAlgorithmException("invalid key parameter spec");
}
pair = mRSAKeyGenerator.generateKeyPair();
break;
case DSA :
if (mDSAKeyGenerator == null)
{
mDSAKeyGenerator = KeyPairGenerator.getInstance("DSA");
}
mDSAKeyGenerator.initialize(keysize);
pair = mDSAKeyGenerator.generateKeyPair();
break;
default :
throw new NoSuchAlgorithmException("Alg " + algorithm);
}
return pair;
}
public KeyPair generateKeyPair(int algorithm, int keysize)
throws NoSuchAlgorithmException
{
return generateKeyPair(algorithm, keysize, false);
}
public static DnsKeyAlgorithm getInstance()
{
if (mInstance == null) mInstance = new DnsKeyAlgorithm();
return mInstance;
}
}