313798 AES and RC2 Mozilla-JSS fixes r=sandeep, sr=wan-teh

This commit is contained in:
glen.beasley%sun.com 2005-11-19 00:20:53 +00:00
Родитель ec25a907bb
Коммит f982ea1547
11 изменённых файлов: 950 добавлений и 132 удалений

Просмотреть файл

@ -151,6 +151,8 @@ public final class JSSProvider extends java.security.Provider {
/////////////////////////////////////////////////////////////
put("AlgorithmParameters.IvAlgorithmParameters",
"org.mozilla.jss.provider.java.security.IvAlgorithmParameters");
put("AlgorithmParameters.RC2AlgorithmParameters",
"org.mozilla.jss.provider.java.security.RC2AlgorithmParameters");
/////////////////////////////////////////////////////////////
// Cipher

Просмотреть файл

@ -179,6 +179,7 @@ public class EncryptionAlgorithm extends Algorithm {
this.mode = mode;
this.padding = padding;
this.blockSize = blockSize;
if(oid!=null) {
oidMap.put(oid, this);
}
@ -387,6 +388,10 @@ public class EncryptionAlgorithm extends Algorithm {
Padding.NONE, IVParameterSpecClasses, 16,
AES_ROOT_OID.subBranch(2), 128);
public static final EncryptionAlgorithm
AES_128_CBC_PAD = new EncryptionAlgorithm(CKM_AES_CBC_PAD, Alg.AES, Mode.CBC,
Padding.PKCS5, IVParameterSpecClasses, 16, null, 128); // no oid
public static final EncryptionAlgorithm
AES_192_ECB = new EncryptionAlgorithm(CKM_AES_ECB, Alg.AES, Mode.ECB,
Padding.NONE, (Class)null, 16, AES_ROOT_OID.subBranch(21), 192);
@ -396,6 +401,10 @@ public class EncryptionAlgorithm extends Algorithm {
Padding.NONE, IVParameterSpecClasses, 16,
AES_ROOT_OID.subBranch(22), 192);
public static final EncryptionAlgorithm
AES_192_CBC_PAD = new EncryptionAlgorithm(CKM_AES_CBC_PAD, Alg.AES, Mode.CBC,
Padding.PKCS5, IVParameterSpecClasses, 16, null, 192); // no oid
public static final EncryptionAlgorithm
AES_256_ECB = new EncryptionAlgorithm(CKM_AES_ECB, Alg.AES, Mode.ECB,
Padding.NONE, (Class)null, 16, AES_ROOT_OID.subBranch(41), 256);
@ -408,4 +417,8 @@ public class EncryptionAlgorithm extends Algorithm {
public static final EncryptionAlgorithm
AES_CBC_PAD = new EncryptionAlgorithm(CKM_AES_CBC_PAD, Alg.AES, Mode.CBC,
Padding.PKCS5, IVParameterSpecClasses, 16, null, 256); // no oid
public static final EncryptionAlgorithm
AES_256_CBC_PAD = AES_CBC_PAD;
}

Просмотреть файл

@ -45,6 +45,8 @@ public interface SymmetricKey {
public static final Type RC4 = Type.RC4;
public static final Type RC2 = Type.RC2;
public static final Type SHA1_HMAC = Type.SHA1_HMAC;
public static final Type AES = Type.AES;
public Type getType();
public CryptoToken getOwningToken();

Просмотреть файл

@ -217,9 +217,14 @@ public final class KeyType {
EncryptionAlgorithm.AES_192_CBC,
EncryptionAlgorithm.AES_256_ECB,
EncryptionAlgorithm.AES_256_CBC,
EncryptionAlgorithm.AES_CBC_PAD,
/* AES CBC PAD is the same as AES_256_CBC_PAD */
/* shouldn't break backward compatiblity 313798*/
//EncryptionAlgorithm.AES_CBC_PAD,
EncryptionAlgorithm.AES_128_CBC_PAD,
EncryptionAlgorithm.AES_192_CBC_PAD,
EncryptionAlgorithm.AES_256_CBC_PAD
},
"DES"
"AES"
);
//////////////////////////////////////////////////////////////

Просмотреть файл

@ -58,6 +58,10 @@ public final class PK11SymKey implements SymmetricKey {
return RC4;
} else if(kt == KeyType.RC2) {
return RC2;
} else if(kt == KeyType.AES) {
return AES;
} else if(kt == KeyType.SHA1_HMAC) {
return SHA1_HMAC;
} else {
Assert.notReached("Unrecognized key type");
return DES;

Просмотреть файл

@ -61,7 +61,8 @@ public class IvAlgorithmParameters extends AlgorithmParametersSpi {
if( clazz != null && !(clazz.isInstance(ivParamSpec)) ) {
Class paramSpecClass = ivParamSpec.getClass();
throw new InvalidParameterSpecException(
"Parameter spec has class " + paramSpecClass.getName());
"Mozilla-JSS IvParameter spec class error"
+ paramSpecClass.getName());
}
return ivParamSpec;
}

Просмотреть файл

@ -0,0 +1,93 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* 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 Network Security Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.jss.provider.java.security;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import javax.crypto.spec.RC2ParameterSpec;
import java.io.IOException;
import org.mozilla.jss.util.Assert;
/**
* This class is only intended to be used to implement
* CipherSpi.getAlgorithmParameters().
*/
public class RC2AlgorithmParameters extends AlgorithmParametersSpi {
private RC2ParameterSpec RC2ParamSpec;
public void engineInit(AlgorithmParameterSpec paramSpec) {
RC2ParamSpec = (RC2ParameterSpec) paramSpec;
}
public AlgorithmParameterSpec engineGetParameterSpec(Class clazz)
throws InvalidParameterSpecException
{
if( clazz != null && !clazz.isInstance(RC2ParamSpec) ) {
Class paramSpecClass = RC2ParamSpec.getClass();
throw new InvalidParameterSpecException(
"RC2 getParameterSpec has class " + paramSpecClass.getName());
}
return RC2ParamSpec;
}
public void engineInit(byte[] params) throws IOException {
Assert.notReached("engineInit(byte[]) not supported");
throw new IOException("engineInit(byte[]) not supported");
}
public void engineInit(byte[] params, String format) throws IOException {
Assert.notReached("engineInit(byte[],String) not supported");
throw new IOException("engineInit(byte[],String) not supported");
}
public byte[] engineGetEncoded() throws IOException {
Assert.notReached("encoding RC2AlgorithmParameters not supported");
throw new IOException("encoding RC2AlgorithmParameters not supported");
}
public byte[] engineGetEncoded(String format) throws IOException {
Assert.notReached("encoding RC2AlgorithmParameters not supported");
throw new IOException("encoding RC2AlgorithmParameters not supported");
}
public String engineToString() {
String str = new String("Mozilla-JSS RC2AlgorithmParameters " + getClass().getName());
return str;
}
}

Просмотреть файл

@ -59,16 +59,16 @@ import org.mozilla.jss.crypto.SymmetricKey;
import org.mozilla.jss.crypto.TokenException;
import org.mozilla.jss.crypto.SecretKeyFacade;
import org.mozilla.jss.crypto.TokenRuntimeException;
import org.mozilla.jss.crypto.JSSSecureRandom;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.util.Assert;
import org.mozilla.jss.pkcs11.PK11SecureRandom;
import org.mozilla.jss.pkcs11.PK11PubKey;
import org.mozilla.jss.pkcs11.PK11PrivKey;
import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
import org.mozilla.jss.asn1.ASN1Util;
import org.mozilla.jss.asn1.BIT_STRING;
import org.mozilla.jss.asn1.InvalidBERException;
import java.security.SecureRandom;
class JSSCipherSpi extends javax.crypto.CipherSpi {
private String algFamily=null;
@ -82,6 +82,8 @@ class JSSCipherSpi extends javax.crypto.CipherSpi {
private KeyWrapAlgorithm wrapAlg = null;
private AlgorithmParameterSpec params = null;
private int blockSize;
//keyStrength is used for RC2ParameterSpec and EncryptionAlgorithm.lookup
private int keyStrength;
private JSSCipherSpi() { }
@ -128,7 +130,6 @@ class JSSCipherSpi extends javax.crypto.CipherSpi {
throws InvalidKeyException, InvalidAlgorithmParameterException
{
try {
// throw away any previous state
cipher = null;
wrapper = null;
@ -162,10 +163,17 @@ class JSSCipherSpi extends javax.crypto.CipherSpi {
SymmetricKey symkey = ((SecretKeyFacade)key).key;
// lookup the encryption algorithm
int keyStrength = symkey.getStrength();
keyStrength = symkey.getStrength();
encAlg = EncryptionAlgorithm.lookup(algFamily, algMode,
algPadding, keyStrength);
blockSize = encAlg.getBlockSize();
if( !token.doesAlgorithm(encAlg) ) {
throw new NoSuchAlgorithmException(
encAlg.toString() + " is not supported by this token " +
token.getName());
}
cipher = token.getCipherContext(encAlg);
if( opmode == Cipher.ENCRYPT_MODE ) {
@ -236,8 +244,21 @@ class JSSCipherSpi extends javax.crypto.CipherSpi {
throws InvalidKeyException, InvalidAlgorithmParameterException
{
try {
engineInit(opmode, key, givenParams.getParameterSpec(null), random);
} catch(InvalidParameterSpecException e) {
AlgorithmParameterSpec gp = null;
if (algFamily.compareToIgnoreCase("RC2") == 0) {
gp = givenParams.getParameterSpec(
javax.crypto.spec.RC2ParameterSpec.class );
} else if (algMode.compareToIgnoreCase("CBC") == 0) {
gp = givenParams.getParameterSpec(
javax.crypto.spec.IvParameterSpec.class );
}
if (gp != null) {
engineInit(opmode, key, gp, random);
} else {
throw new InvalidAlgorithmParameterException("Unknown Parameter Spec");
}
} catch(Exception e) {
throw new InvalidAlgorithmParameterException(e.getMessage());
}
}
@ -252,24 +273,35 @@ class JSSCipherSpi extends javax.crypto.CipherSpi {
}
}
private static AlgorithmParameterSpec
private AlgorithmParameterSpec
generateAlgParams(Algorithm alg, int blockSize) throws InvalidKeyException {
Class paramClass = alg.getParameterClass();
if( paramClass == null ) {
Class [] paramClasses = alg.getParameterClasses();
AlgorithmParameterSpec algParSpec = null;
if( paramClasses == null ) {
// no parameters are needed
return null;
} else if( paramClass.equals( IvParameterSpec.class ) ) {
// generate an IV
byte[] iv = new byte[blockSize];
PK11SecureRandom rng = new PK11SecureRandom();
rng.nextBytes(iv);
return new IvParameterSpec(iv);
} else {
// I don't know any other parameter types.
throw new InvalidKeyException(
"Unable to generate parameters of type " +paramClass.getName());
}
// generate an IV
byte[] iv = new byte[blockSize];
try {
SecureRandom random = SecureRandom.getInstance("pkcs11prng",
"Mozilla-JSS");
random.nextBytes(iv);
} catch (Exception e) {
Assert.notReached(e.getMessage());
}
for (int i = 0; i < paramClasses.length; i ++) {
if( paramClasses[i].equals( javax.crypto.spec.IvParameterSpec.class ) ) {
algParSpec = new javax.crypto.spec.IvParameterSpec(iv);
break;
} else if ( paramClasses[i].equals( RC2ParameterSpec.class ) ) {
algParSpec = new RC2ParameterSpec(keyStrength, iv);
break;
}
}
return algParSpec;
}
private static class NoAlgParams implements AlgorithmParameterSpec { }
@ -293,22 +325,19 @@ class JSSCipherSpi extends javax.crypto.CipherSpi {
}
public AlgorithmParameters engineGetParameters() {
if( params instanceof IvParameterSpec ) {
try {
AlgorithmParameters algParams =
AlgorithmParameters.getInstance("IvAlgorithmParameters",
"Mozilla-JSS");
algParams.init(params);
return algParams;
AlgorithmParameters algParams = null;
try {
if(( params instanceof IvParameterSpec )
|| ( params instanceof RC2ParameterSpec )) {
algParams = AlgorithmParameters.getInstance(algFamily);
algParams.init(params);
}
} catch(NoSuchAlgorithmException nsae) {
Assert.notReached(nsae.getMessage());
} catch( NoSuchProviderException nspe) {
Assert.notReached(nspe.getMessage());
} catch(InvalidParameterSpecException ipse) {
Assert.notReached(ipse.getMessage());
}
}
return null;
return algParams;
}
public int engineGetOutputSize(int inputLen) {

Просмотреть файл

@ -0,0 +1,413 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* 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 the Netscape Security Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.jss.tests;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import org.mozilla.jss.CertDatabaseException;
import org.mozilla.jss.KeyDatabaseException;
import org.mozilla.jss.crypto.*;
import org.mozilla.jss.CryptoManager;
import java.security.Provider;
import java.security.Security;
import java.security.AlgorithmParameters;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.spec.RC2ParameterSpec;
import javax.crypto.KeyGenerator;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.SecureRandom;
/**
*
*/
public class JCASymKeyGen {
static final String MOZ_PROVIDER_NAME = "Mozilla-JSS";
byte[] plainText16Bytes = "Firefox rules!".getBytes(); /* 16 bytes */
byte[] plainText18Bytes = "Thunderbird rules!".getBytes(); /* 18 bytes */
/**
* Default constructor
*/
public JCASymKeyGen( String certDbLoc) {
try {
CryptoManager.initialize(certDbLoc);
CryptoManager cm = CryptoManager.getInstance();
CryptoToken token = cm.getInternalCryptoToken();
} catch (AlreadyInitializedException ex) {
ex.printStackTrace();
System.exit(1);
} catch (CertDatabaseException ex) {
ex.printStackTrace();
System.exit(1);
} catch (CryptoManager.NotInitializedException ex) {
ex.printStackTrace();
System.exit(1);
} catch (GeneralSecurityException ex) {
ex.printStackTrace();
System.exit(1);
} catch (KeyDatabaseException ex) {
ex.printStackTrace();
System.exit(1);
}
}
/**
*
* @param
*/
public javax.crypto.SecretKey genSecretKey(String keyType, String provider){
javax.crypto.SecretKey key = null;
javax.crypto.KeyGenerator kg = null;
try {
kg = KeyGenerator.getInstance(keyType,
provider);
if (keyType.equals("AES") || keyType.equals("RC2")) {
kg.init(128); //JDK 1.4 and 1.5 only supports 128 keys for AES
}
System.out.println("Key " + keyType + " generation done by "
+ kg.getProvider().toString());
key = kg.generateKey();
if( !checkAlgorithm(key, keyType) ) {
throw new Exception("Error: " + key.getAlgorithm() +
" algorithm");
}
//System.out.println("The length of the generated key in bits: " +
// (key.getEncoded().length * 8) +
// " " + key.getAlgorithm() );
} catch (NoSuchProviderException ex) {
ex.printStackTrace();
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
return key;
}
/**
*
* @param keyType
* @param provider
* @return
*/
public javax.crypto.SecretKey genPBESecretKey(String keyType,
String provider){
javax.crypto.SecretKey key = null;
javax.crypto.SecretKeyFactory kf = null;
try {
char[] pw = "thunderbird".toCharArray();
byte[] salt = new byte[8];
SecureRandom random = SecureRandom.getInstance("pkcs11prng",
MOZ_PROVIDER_NAME);
random.nextBytes(salt);
int iterationCount = 2;
kf = SecretKeyFactory.getInstance(keyType,
provider);
PBEKeySpec keySpec = new PBEKeySpec(pw, salt, iterationCount);
key = (SecretKeyFacade) kf.generateSecret(keySpec);
//todo this should work as well
//PBEKeySpec pbeKeySpec = new PBEKeySpec(pw));
// key = kf.generateSecret(pbeKeySpec);
System.out.println("Key " + keyType + " generation done by "
+ kf.getProvider().toString());
//System.out.println("The length of the generated key in bits: " +
// (key.getEncoded().length * 8) +
// " " + key.getAlgorithm() );
} catch (NoSuchProviderException ex) {
ex.printStackTrace();
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
return key;
}
/**
*
* @param sKey
* @param AlgType
* @param provider
*/
public void testCipher(javax.crypto.SecretKey sKey, String algFamily,
String algType, String providerForEncrypt, String providerForDecrypt)
throws Exception {
try {
// if no padding is used plainText needs to be fixed length
// block divisable by 8 bytes
byte[] plaintext = plainText16Bytes;
if (algType.endsWith("PKCS5Padding")) {
plaintext = plainText18Bytes;
}
//encypt
Cipher cipher = Cipher.getInstance(algType, providerForEncrypt);
AlgorithmParameters ap = null;
byte[] encodedAlgParams = null;
AlgorithmParameterSpec RC2ParSpec = null;
if (algFamily.compareToIgnoreCase("RC2")==0) {
//JDK 1.4 requires you to pass in generated algorithm
//parameters for RC2 (JDK 1.5 does not).
byte[] iv = new byte[8];
SecureRandom random = SecureRandom.getInstance("pkcs11prng",
MOZ_PROVIDER_NAME);
random.nextBytes(iv);
RC2ParSpec = new RC2ParameterSpec(128, iv);
cipher.init(Cipher.ENCRYPT_MODE, sKey, RC2ParSpec);
} else {
cipher.init(Cipher.ENCRYPT_MODE, sKey);
//generate the algorithm Parameters; they need to be
//the same for encrypt/decrypt if they are needed.
ap = cipher.getParameters();
if (ap != null) {
//get parameters to store away as example.
encodedAlgParams = ap.getEncoded();
}
}
byte[] ciphertext = cipher.doFinal(plaintext);
//decrypt
cipher = Cipher.getInstance(algType, providerForDecrypt);
if (encodedAlgParams == null)
if (RC2ParSpec != null)
// JDK 1.4 RC2
cipher.init(Cipher.DECRYPT_MODE, sKey, RC2ParSpec);
else
cipher.init(Cipher.DECRYPT_MODE, sKey);
else {
//retrieve the algorithmParameters from the encoded array
AlgorithmParameters aps =
AlgorithmParameters.getInstance(algFamily);
aps.init(encodedAlgParams);
cipher.init(Cipher.DECRYPT_MODE, sKey, aps);
}
byte[] recovered = cipher.doFinal(ciphertext);
if (java.util.Arrays.equals(plaintext, recovered) ) {
// System.out.println(providerForEncrypt + " encrypted & " +
// providerForDecrypt + " decrypted using " +
// algType + " successful.");
} else {
throw new Exception("ERROR: " + providerForEncrypt +
" and " + providerForDecrypt + " failed for "
+ algType );
}
} catch (InvalidKeyException ex) {
ex.printStackTrace();
} catch (javax.crypto.BadPaddingException ex) {
ex.printStackTrace();
} catch (NoSuchProviderException ex) {
ex.printStackTrace();
} catch (javax.crypto.NoSuchPaddingException ex) {
ex.printStackTrace();
} catch (javax.crypto.IllegalBlockSizeException ex) {
ex.printStackTrace();
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
}
public static void main(String args[]) {
String certDbLoc = ".";
// Mozilla supported symmetric key ciphers and algorithms
// Note JCE supports algorthm/ECB/PKCS5Padding and JSS does
// not support algorithms in ECB mode with PKCS5Padding
String [][] symKeyTable = {
{"DES", "DES/ECB/NoPadding", "DES/CBC/PKCS5Padding",
"DES/CBC/NoPadding" },
{"DESede", "DESede/ECB/NoPadding", "DESede/CBC/PKCS5Padding",
"DESede/CBC/NoPadding" },
{"AES", "AES/ECB/NoPadding", "AES/CBC/NoPadding",
"AES/CBC/PKCS5Padding"},
{"RC2", "RC2/CBC/NoPadding", "RC2/CBC/PKCS5Padding"},
//{"RC4", "RC4"}, todo
//{PBAHmacSHA1"}, todo
{"PBEWithMD5AndDES", "DES/ECB/NoPadding"},
//todo "DES/CBC/PKCS5Padding", "DES/CBC/NoPadding" },
{"PBEWithSHA1AndDES"},
{"PBEWithSHA1AndDESede", "DESede/ECB/NoPadding"},
//{"PBEWithSHA1And128RC4"}, todo
};
if ( args.length == 1 ) {
certDbLoc = args[0];
} else {
System.out.println(
"USAGE: java org.mozilla.jss.tests.JCASymKeyGen" +
" <certDbPath> ");
System.exit(1);
}
//If the IBMJCE provider exists tests with it otherwise
//use the SunJCE provider.
String otherProvider = new String("IBMJCE");
Provider p = null;
p = Security.getProvider(otherProvider);
if (p == null) {
otherProvider = new String("SunJCE");
p = Security.getProvider(otherProvider);
if (p == null){
System.out.println("unable to find IBMJCE or SunJCE providers");
System.exit(1);
}
}
JCASymKeyGen skg = new JCASymKeyGen(certDbLoc);
System.out.println(otherProvider + ": " + p.getInfo());
p = Security.getProvider(MOZ_PROVIDER_NAME);
System.out.println(MOZ_PROVIDER_NAME + ": " + p.getInfo());
javax.crypto.SecretKey mozKey = null;
try {
for (int i = 0 ; i < symKeyTable.length; i++) {
try {
//generate the key using mozilla
if (symKeyTable[i][0].startsWith("PBE") == true) {
mozKey = skg.genPBESecretKey(symKeyTable[i][0],
MOZ_PROVIDER_NAME);
} else {
mozKey = skg.genSecretKey(symKeyTable[i][0],
MOZ_PROVIDER_NAME);
}
} catch(Exception e) {
System.out.println("unable to generate key: " +
symKeyTable[i][0] + " " + e.getMessage());
}
//test the cihper algorithms for this keyType
for (int a = 1 ; a < symKeyTable[i].length; a++){
//encrypt/decrypt with Mozilla Provider
skg.testCipher(mozKey, symKeyTable[i][0], symKeyTable[i][a],
MOZ_PROVIDER_NAME, MOZ_PROVIDER_NAME);
try {
//check to see if the otherProvider we are testing
//against supports the algorithm.
Cipher cipher = Cipher.getInstance(symKeyTable[i][a],
otherProvider);
} catch (Exception e) {
System.out.println(MOZ_PROVIDER_NAME + " only supports "
+ symKeyTable[i][a]);
//therefore don't try comparison
continue;
}
//encrypt with Mozilla, and Decrypt with otherProvider
skg.testCipher(mozKey, symKeyTable[i][0], symKeyTable[i][a],
MOZ_PROVIDER_NAME, otherProvider);
//encrypt with default otherProvider and decrypt with Mozilla
skg.testCipher(mozKey, symKeyTable[i][0], symKeyTable[i][a],
otherProvider, MOZ_PROVIDER_NAME);
System.out.println(MOZ_PROVIDER_NAME + " and " + otherProvider
+ " tested " + symKeyTable[i][a]);
}
}
} catch(Exception e) {
e.printStackTrace();
System.exit(1);
}
//end of main
System.exit(0);
}
/**
* Validate if the key algorithm of a given SecretKey
* is the same as expected.
* @param SecretKey k
* @param String algorithm
* @return boolean status
*/
private boolean checkAlgorithm(SecretKey k, String alg) {
boolean status = false;
if( k.getAlgorithm().equals(alg) ) {
status = true;
}
return status;
}
/**
* Validate if the key length of a given SecretKey
* is the same as expected.
* @param SecretKey k
* @param int key length
* @return boolean status
*/
private boolean checkKeyLength(SecretKey k, int len) {
boolean status = false;
byte[] keyData = k.getEncoded();
if( keyData.length == len ) {
status = true;
}
return status;
}
/**
* Turns array of bytes into string
*
* @param buf Array of bytes to convert to hex string
* @return Generated hex string
*/
private String asHex(byte buf[]) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}
}

Просмотреть файл

@ -41,121 +41,359 @@ import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.util.Assert;
import org.mozilla.jss.util.Password;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
import org.mozilla.jss.CertDatabaseException;
import org.mozilla.jss.KeyDatabaseException;
import java.security.GeneralSecurityException;
import org.mozilla.jss.pkcs11.PK11SecureRandom;
import javax.crypto.spec.RC2ParameterSpec;
import java.util.*;
/**
* Most of this code is Deprecated look at JCASymKeyGen.java for sample.
*/
public class SymKeyGen {
private CryptoToken token = null;
byte[] plainText16Bytes = "Firefox rules!".getBytes(); /* 16 bytes */
byte[] plainText18Bytes = "Thunderbird rules!".getBytes(); /* 18 bytes */
public static void main(String args[]) {
public SymmetricKey genPBEKey(PBEAlgorithm alg,
SymmetricKey.Type keyType, int keyStrength)
throws Exception {
try {
CryptoManager.initialize(".");
CryptoManager cm = CryptoManager.getInstance();
CryptoToken token = cm.getInternalCryptoToken();
SymmetricKey key = null;
byte[] keyData;
KeyGenerator kg = token.getKeyGenerator(alg);
// DES key
KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES);
SymmetricKey key = kg.generate();
if( key.getType() != SymmetricKey.DES ) {
throw new Exception("wrong algorithm");
}
if( ! key.getOwningToken().equals( token ) ) {
throw new Exception("wrong token");
}
if( key.getStrength() != 56 ) {
throw new Exception("wrong strength");
}
keyData = key.getKeyData();
if( keyData.length != 8 ) {
throw new Exception("key data wrong length: " + keyData.length);
}
System.out.println("DES key is correct");
IVParameterSpec iv = new IVParameterSpec(
new byte[]{ (byte)0xff, (byte)0x00, (byte)0xff, (byte)0x00,
(byte)0xff, (byte)0x00, (byte)0xff, (byte)0x00 } );
Cipher cipher = token.getCipherContext(EncryptionAlgorithm.DES_CBC_PAD);
cipher.initEncrypt(key, iv);
byte[] plaintext = new byte[] { (byte)0xff, (byte)0x00 };
byte[] ciphertext = cipher.doFinal(plaintext);
cipher.initDecrypt(key, iv);
byte[] recovered = cipher.doFinal(ciphertext);
if( recovered.length != plaintext.length ) {
throw new Exception("Recovered plaintext has different length ("+
recovered.length+") than original ("+plaintext.length+")");
}
for(int i=0; i < recovered.length; i++) {
if( plaintext[i] != recovered[i] ) {
throw new Exception("Recovered plaintext differs from original"
+ " at position "+i);
}
}
System.out.println("DES encryption succeeded");
// DES3 key
kg = token.getKeyGenerator(KeyGenAlgorithm.DES3);
key = kg.generate();
if( key.getType() != SymmetricKey.DES3 ) {
throw new Exception("wrong algorithm");
}
if( ! key.getOwningToken().equals( token ) ) {
throw new Exception("wrong token");
}
if( key.getStrength() != 168 ) {
throw new Exception("wrong strength");
}
keyData = key.getKeyData();
if( keyData.length != 24 ) {
throw new Exception("key data wrong length: " + keyData.length);
}
System.out.println("DES3 key is correct");
// RC4 key
kg = token.getKeyGenerator(KeyGenAlgorithm.RC4);
kg.initialize(128);
key = kg.generate();
if( key.getType() != SymmetricKey.RC4 ) {
throw new Exception("wrong algorithm");
}
if( ! key.getOwningToken().equals( token ) ) {
throw new Exception("wrong token");
}
if( key.getStrength() != 128 ) {
throw new Exception("wrong strength");
}
keyData = key.getKeyData();
if( keyData.length != 16 ) {
throw new Exception("key data wrong length: " + keyData.length);
}
System.out.println("RC4 key is correct");
// PBE MD5 DES CBC
kg = token.getKeyGenerator(PBEAlgorithm.PBE_MD5_DES_CBC);
try {
kg.initialize(56);
throw new Exception("ERROR: Initializing PBE key with strength "+
"succeeded");
} catch( InvalidAlgorithmParameterException e) { }
Password pass = new Password( ("passwd").toCharArray() );
byte[] salt = new byte[] { (byte)0xff, (byte)0x00, (byte)0xff };
//this is debug code you don't initialize
//PBE algs with key Strength doing this should throw
//InvaldAlgortithmParameterException
kg.initialize(keyStrength);
throw new Exception("ERROR: Initializing PBE key with strength " +
keyStrength + " succeeded");
} catch( InvalidAlgorithmParameterException e) {
}
Password pass = new Password( ("passwd1").toCharArray() );
byte[] salt = genSalt(alg.getSaltLength());
PBEKeyGenParams kgp = new PBEKeyGenParams(pass, salt, 2);
kg.initialize(kgp);
key = kg.generate();
if( key.getType() != SymmetricKey.DES ) {
if( key.getType() != keyType ) {
throw new Exception("Wrong key type: "+key.getType());
}
if( ! key.getOwningToken().equals( token ) ) {
throw new Exception("wrong token");
}
if( key.getStrength() != 56 && key.getStrength() != 64) {
if( key.getStrength() != keyStrength ) {
throw new Exception("wrong strength: "+key.getStrength());
}
return key;
}
public SymmetricKey genPBAKey(KeyGenAlgorithm alg,
SymmetricKey.Type keyType, int keyStrength)
throws Exception {
SymmetricKey key = null;
byte[] keyData;
KeyGenerator kg = token.getKeyGenerator(alg);
try {
//this is debug code you don't initialize
//PBE algs with key Strength doing this should throw
//InvaldAlgortithmParameterException
kg.initialize(keyStrength);
throw new Exception("ERROR: Initializing PBE key with strength "+
keyStrength + " succeeded");
} catch( InvalidAlgorithmParameterException e) {
}
Password pass = new Password( ("passwd1").toCharArray() );
byte[] salt = genSalt(8);
PBEKeyGenParams kgp = new PBEKeyGenParams(pass, salt, 2);
kg.initialize(kgp);
key = kg.generate();
if( key.getType() != keyType ) {
throw new Exception("Wrong key type: "+key.getType());
}
if( ! key.getOwningToken().equals( token ) ) {
throw new Exception("wrong token");
}
if( key.getStrength() != keyStrength ) {
throw new Exception("wrong strength: "+key.getStrength());
}
return key;
}
public SymmetricKey genSymKey(KeyGenAlgorithm alg, SymmetricKey.Type keyType
, int keyStrength, int keyLength)
throws Exception {
SymmetricKey key = null;
byte[] keyData;
KeyGenerator kg = token.getKeyGenerator(alg);
if (alg == KeyGenAlgorithm.AES || alg == KeyGenAlgorithm.RC4
|| alg == KeyGenAlgorithm.RC2) {
kg.initialize (keyStrength);
}
key = kg.generate();
if( key.getType() != keyType ) {
throw new Exception("wrong algorithm");
}
if( ! key.getOwningToken().equals( token ) ) {
throw new Exception("wrong token");
}
if( key.getStrength() != keyStrength ) {
throw new Exception("wrong strength");
}
keyData = key.getKeyData();
if( keyData.length != 8 ) {
if( keyData.length != keyLength ) {
throw new Exception("key data wrong length: " + keyData.length);
}
System.out.println("PBE key is correct");
return key;
}
public boolean cipherTest(SymmetricKey key, EncryptionAlgorithm eAlg
) throws Exception {
boolean bStatus = false;
int ivLength = 0;
AlgorithmParameterSpec algParSpec = null;
Cipher cipher = null;
cipher = token.getCipherContext(eAlg);
// if no padding is used plainText needs to be fixed length
// block divisable by 8 bytes
byte[] plaintext = plainText18Bytes;
if ((eAlg.getMode() == EncryptionAlgorithm.Mode.CBC ||
eAlg.getMode() == EncryptionAlgorithm.Mode.ECB ) &&
eAlg.getPadding() == EncryptionAlgorithm.Padding.NONE) {
plaintext = plainText16Bytes;
}
// size 0 means this algorithm does not take an IV.
// you need to use the same IV for Encrypt/Decrypt
ivLength = eAlg.getIVLength();
if (ivLength != 0 ) {
algParSpec = genIV(ivLength);
}
if (key.getType() == (SymmetricKey.Type) SymmetricKey.RC2) {
byte[] iv = new byte[ivLength];
PK11SecureRandom rng = new PK11SecureRandom();
rng.nextBytes(iv);
algParSpec = new RC2ParameterSpec(40, iv);
}
if (algParSpec == null) {
cipher.initEncrypt(key);
} else {
cipher.initEncrypt(key, algParSpec);
}
byte[] ciphertext = cipher.doFinal(plaintext);
if (ivLength == 0) {
cipher.initDecrypt(key);
} else {
cipher.initDecrypt(key, algParSpec);
}
byte[] recovered = cipher.doFinal(ciphertext);
if( recovered.length != plaintext.length ) {
throw new Exception("Recovered plaintext has different length ("+
recovered.length+") than original ("+plaintext.length+")");
}
if (java.util.Arrays.equals(plaintext, recovered) ) {
bStatus = true;
} else {
throw new Exception("ERROR: unable to recover plaintext");
}
return bStatus; // no exception was thrown.
}
private SymKeyGen( String certDbLoc) {
try {
CryptoManager.initialize(certDbLoc);
CryptoManager cm = CryptoManager.getInstance();
token = cm.getInternalCryptoToken();
} catch (AlreadyInitializedException ex) {
ex.printStackTrace();
} catch (CertDatabaseException ex) {
ex.printStackTrace();
} catch (CryptoManager.NotInitializedException ex) {
ex.printStackTrace();
} catch (GeneralSecurityException ex) {
ex.printStackTrace();
} catch (KeyDatabaseException ex) {
ex.printStackTrace();
}
}
public IVParameterSpec genIV(int blockSize) throws Exception {
// generate an IV
byte[] iv = new byte[blockSize];
PK11SecureRandom rng = new PK11SecureRandom();
rng.nextBytes(iv);
return new IVParameterSpec(iv);
}
public byte[] genSalt(int saltSize) throws Exception {
byte[] salt = new byte[saltSize];
PK11SecureRandom rng = new PK11SecureRandom();
rng.nextBytes(salt);
return salt;
}
class alg {
public KeyGenAlgorithm sAlg;
public SymmetricKey.Type keyType;
public int size;
public int blkSize;
List ciphers = new LinkedList();
public alg (KeyGenAlgorithm alg, SymmetricKey.Type kType, int sz, int bSize) {
sAlg = alg;
keyType = kType;
size = sz;
blkSize = bSize;
}
public void setEncAlgs(List c) {
ciphers = c;
}
}
public static void main(String args[]) {
try {
if ( args.length < 1 ) {
System.out.println("Usage: java org.mozilla.jss.tests." +
"SymKeyGen <dbdir>");
System.exit(1);
}
SymKeyGen skg = new SymKeyGen(args[0]);
SymmetricKey key = null;
//DES Key
key = skg.genSymKey(KeyGenAlgorithm.DES, SymmetricKey.DES, 56, 8);
skg.cipherTest(key, EncryptionAlgorithm.DES_CBC_PAD);
skg.cipherTest(key, EncryptionAlgorithm.DES_CBC);
skg.cipherTest(key, EncryptionAlgorithm.DES_ECB);
System.out.println("DES key and cipher tests correct");
// DES3 key
key = skg.genSymKey(KeyGenAlgorithm.DES3, SymmetricKey.DES3, 168, 24);
skg.cipherTest(key, EncryptionAlgorithm.DES3_CBC_PAD);
skg.cipherTest(key, EncryptionAlgorithm.DES3_CBC);
skg.cipherTest(key, EncryptionAlgorithm.DES3_ECB);
System.out.println("DESede key and cipher tests correct");
// AES 128 key
key = skg.genSymKey(KeyGenAlgorithm.AES, SymmetricKey.AES, 128, 128/8);
skg.cipherTest(key, EncryptionAlgorithm.AES_128_CBC);
skg.cipherTest(key, EncryptionAlgorithm.AES_128_ECB);
skg.cipherTest(key, EncryptionAlgorithm.AES_128_CBC_PAD);
System.out.println("AES 128 key and cipher tests correct");
// AES 192 key
key = skg.genSymKey(KeyGenAlgorithm.AES, SymmetricKey.AES, 192, 192/8);
skg.cipherTest(key, EncryptionAlgorithm.AES_192_CBC);
skg.cipherTest(key, EncryptionAlgorithm.AES_192_ECB);
skg.cipherTest(key, EncryptionAlgorithm.AES_192_CBC_PAD);
System.out.println("AES 192 key and cipher tests correct");
// AES 256 key
key = skg.genSymKey(KeyGenAlgorithm.AES, SymmetricKey.AES, 256, 256/8);
skg.cipherTest(key, EncryptionAlgorithm.AES_256_CBC);
skg.cipherTest(key, EncryptionAlgorithm.AES_256_ECB);
skg.cipherTest(key, EncryptionAlgorithm.AES_256_CBC_PAD);
System.out.println("AES 256 key and cipher tests correct");
// RC2 Key
key = skg.genSymKey(KeyGenAlgorithm.RC2, SymmetricKey.RC2, 40, 5);
skg.cipherTest(key, EncryptionAlgorithm.RC2_CBC);
skg.cipherTest(key, EncryptionAlgorithm.RC2_CBC_PAD);
System.out.println("RC2 key and cipher tests correct");
// RC4 key
key = skg.genSymKey(KeyGenAlgorithm.RC4, SymmetricKey.RC4, 128, 128/8);
skg.cipherTest(key, EncryptionAlgorithm.RC4);
System.out.println("RC4 key and cipher tests correct");
//Todo
//KeyGenAlgorithm.PBA_SHA1_HMAC, SymmetricKey.SHA1_HMAC, 160);
//PBE key gen test.
// PBEAlgorithm.PBE_MD2_DES_CBC
key = skg.genPBEKey(PBEAlgorithm.PBE_MD2_DES_CBC, SymmetricKey.DES,
56);
skg.cipherTest(key, EncryptionAlgorithm.DES_CBC_PAD);
skg.cipherTest(key, EncryptionAlgorithm.DES_CBC);
skg.cipherTest(key, EncryptionAlgorithm.DES_ECB);
//PBEAlgorithm.PBE_MD5_DES_CBC
key = skg.genPBEKey(PBEAlgorithm.PBE_MD5_DES_CBC, SymmetricKey.DES,
56);
skg.cipherTest(key, EncryptionAlgorithm.DES_CBC_PAD);
skg.cipherTest(key, EncryptionAlgorithm.DES_CBC);
skg.cipherTest(key, EncryptionAlgorithm.DES_ECB);
//PBEAlgorithm.PBE_SHA1_DES_CBC
key = skg.genPBEKey(PBEAlgorithm.PBE_SHA1_DES_CBC, SymmetricKey.DES,
64);
skg.cipherTest(key, EncryptionAlgorithm.DES_CBC_PAD);
skg.cipherTest(key, EncryptionAlgorithm.DES_CBC);
skg.cipherTest(key, EncryptionAlgorithm.DES_ECB);
//PBEAlgorithm.PBE_SHA1_DES3_CBC
key = skg.genPBEKey(PBEAlgorithm.PBE_SHA1_DES3_CBC, SymmetricKey.DES3,
168);
skg.cipherTest(key, EncryptionAlgorithm.DES3_CBC_PAD);
skg.cipherTest(key, EncryptionAlgorithm.DES3_CBC);
skg.cipherTest(key, EncryptionAlgorithm.DES3_ECB);
//PBEAlgorithm.PBE_SHA1_RC2_40_CBC
key = skg.genPBEKey(PBEAlgorithm.PBE_SHA1_RC2_40_CBC, SymmetricKey.RC2,
40);
skg.cipherTest(key, EncryptionAlgorithm.RC2_CBC);
skg.cipherTest(key, EncryptionAlgorithm.RC2_CBC_PAD);
//PBEAlgorithm.PBE_SHA1_RC2_128_CBC
key = skg.genPBEKey(PBEAlgorithm.PBE_SHA1_RC2_128_CBC, SymmetricKey.RC2,
128);
skg.cipherTest(key, EncryptionAlgorithm.RC2_CBC);
skg.cipherTest(key, EncryptionAlgorithm.RC2_CBC_PAD);
//PBEAlgorithm.PBE_SHA1_RC4_40
key = skg.genPBEKey(PBEAlgorithm.PBE_SHA1_RC4_40, SymmetricKey.RC4,
40);
skg.cipherTest(key, EncryptionAlgorithm.RC4);
//PBEAlgorithm.PBE_SHA1_RC4_128
key = skg.genPBEKey(PBEAlgorithm.PBE_SHA1_RC4_128, SymmetricKey.RC4,
128);
skg.cipherTest(key, EncryptionAlgorithm.RC4);
System.out.println("Password Based key generation tests correct");
} catch(Exception e) {
e.printStackTrace();

Просмотреть файл

@ -419,6 +419,24 @@ $result >>=8;
$result and print "Disable FIPSMODE returned $result\n";
print_case_result ($result,"FIPSMODE disabled");
#
# Test SecretKeys
#
print "============= Start Secret Key Gen and Ciphers\n";
$result = system("$java org.mozilla.jss.tests.SymKeyGen $testdir");
$result >>=8;
$result and print "SymKeyGen returned $result\n";
print_case_result ($result,"SymKeyGen successful");
#
# Test Mozilla-JSS SecretKeys
#
print "============= Start Mozilla-JSS Secret Key Gen and Ciphers\n";
$result = system("$java org.mozilla.jss.tests.JCASymKeyGen $testdir");
$result >>=8;
$result and print "JCASymKeyGen returned $result\n";
print_case_result ($result,"JCASymKeyGen successful");
$portJSSEServer=$portJSSEServer+1;
#