зеркало из https://github.com/mozilla/pjs.git
313798 AES and RC2 Mozilla-JSS fixes r=sandeep, sr=wan-teh
This commit is contained in:
Родитель
ec25a907bb
Коммит
f982ea1547
|
@ -151,6 +151,8 @@ public final class JSSProvider extends java.security.Provider {
|
||||||
/////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////
|
||||||
put("AlgorithmParameters.IvAlgorithmParameters",
|
put("AlgorithmParameters.IvAlgorithmParameters",
|
||||||
"org.mozilla.jss.provider.java.security.IvAlgorithmParameters");
|
"org.mozilla.jss.provider.java.security.IvAlgorithmParameters");
|
||||||
|
put("AlgorithmParameters.RC2AlgorithmParameters",
|
||||||
|
"org.mozilla.jss.provider.java.security.RC2AlgorithmParameters");
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////
|
||||||
// Cipher
|
// Cipher
|
||||||
|
|
|
@ -179,6 +179,7 @@ public class EncryptionAlgorithm extends Algorithm {
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
this.padding = padding;
|
this.padding = padding;
|
||||||
this.blockSize = blockSize;
|
this.blockSize = blockSize;
|
||||||
|
|
||||||
if(oid!=null) {
|
if(oid!=null) {
|
||||||
oidMap.put(oid, this);
|
oidMap.put(oid, this);
|
||||||
}
|
}
|
||||||
|
@ -387,6 +388,10 @@ public class EncryptionAlgorithm extends Algorithm {
|
||||||
Padding.NONE, IVParameterSpecClasses, 16,
|
Padding.NONE, IVParameterSpecClasses, 16,
|
||||||
AES_ROOT_OID.subBranch(2), 128);
|
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
|
public static final EncryptionAlgorithm
|
||||||
AES_192_ECB = new EncryptionAlgorithm(CKM_AES_ECB, Alg.AES, Mode.ECB,
|
AES_192_ECB = new EncryptionAlgorithm(CKM_AES_ECB, Alg.AES, Mode.ECB,
|
||||||
Padding.NONE, (Class)null, 16, AES_ROOT_OID.subBranch(21), 192);
|
Padding.NONE, (Class)null, 16, AES_ROOT_OID.subBranch(21), 192);
|
||||||
|
@ -395,6 +400,10 @@ public class EncryptionAlgorithm extends Algorithm {
|
||||||
AES_192_CBC = new EncryptionAlgorithm(CKM_AES_CBC, Alg.AES, Mode.CBC,
|
AES_192_CBC = new EncryptionAlgorithm(CKM_AES_CBC, Alg.AES, Mode.CBC,
|
||||||
Padding.NONE, IVParameterSpecClasses, 16,
|
Padding.NONE, IVParameterSpecClasses, 16,
|
||||||
AES_ROOT_OID.subBranch(22), 192);
|
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
|
public static final EncryptionAlgorithm
|
||||||
AES_256_ECB = new EncryptionAlgorithm(CKM_AES_ECB, Alg.AES, Mode.ECB,
|
AES_256_ECB = new EncryptionAlgorithm(CKM_AES_ECB, Alg.AES, Mode.ECB,
|
||||||
|
@ -404,8 +413,12 @@ public class EncryptionAlgorithm extends Algorithm {
|
||||||
AES_256_CBC = new EncryptionAlgorithm(CKM_AES_CBC, Alg.AES, Mode.CBC,
|
AES_256_CBC = new EncryptionAlgorithm(CKM_AES_CBC, Alg.AES, Mode.CBC,
|
||||||
Padding.NONE, IVParameterSpecClasses, 16,
|
Padding.NONE, IVParameterSpecClasses, 16,
|
||||||
AES_ROOT_OID.subBranch(42), 256);
|
AES_ROOT_OID.subBranch(42), 256);
|
||||||
|
|
||||||
public static final EncryptionAlgorithm
|
public static final EncryptionAlgorithm
|
||||||
AES_CBC_PAD = new EncryptionAlgorithm(CKM_AES_CBC_PAD, Alg.AES, Mode.CBC,
|
AES_CBC_PAD = new EncryptionAlgorithm(CKM_AES_CBC_PAD, Alg.AES, Mode.CBC,
|
||||||
Padding.PKCS5, IVParameterSpecClasses, 16, null, 256); // no oid
|
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 RC4 = Type.RC4;
|
||||||
public static final Type RC2 = Type.RC2;
|
public static final Type RC2 = Type.RC2;
|
||||||
public static final Type SHA1_HMAC = Type.SHA1_HMAC;
|
public static final Type SHA1_HMAC = Type.SHA1_HMAC;
|
||||||
|
public static final Type AES = Type.AES;
|
||||||
|
|
||||||
public Type getType();
|
public Type getType();
|
||||||
|
|
||||||
public CryptoToken getOwningToken();
|
public CryptoToken getOwningToken();
|
||||||
|
|
|
@ -217,9 +217,14 @@ public final class KeyType {
|
||||||
EncryptionAlgorithm.AES_192_CBC,
|
EncryptionAlgorithm.AES_192_CBC,
|
||||||
EncryptionAlgorithm.AES_256_ECB,
|
EncryptionAlgorithm.AES_256_ECB,
|
||||||
EncryptionAlgorithm.AES_256_CBC,
|
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;
|
return RC4;
|
||||||
} else if(kt == KeyType.RC2) {
|
} else if(kt == KeyType.RC2) {
|
||||||
return RC2;
|
return RC2;
|
||||||
|
} else if(kt == KeyType.AES) {
|
||||||
|
return AES;
|
||||||
|
} else if(kt == KeyType.SHA1_HMAC) {
|
||||||
|
return SHA1_HMAC;
|
||||||
} else {
|
} else {
|
||||||
Assert.notReached("Unrecognized key type");
|
Assert.notReached("Unrecognized key type");
|
||||||
return DES;
|
return DES;
|
||||||
|
|
|
@ -61,7 +61,8 @@ public class IvAlgorithmParameters extends AlgorithmParametersSpi {
|
||||||
if( clazz != null && !(clazz.isInstance(ivParamSpec)) ) {
|
if( clazz != null && !(clazz.isInstance(ivParamSpec)) ) {
|
||||||
Class paramSpecClass = ivParamSpec.getClass();
|
Class paramSpecClass = ivParamSpec.getClass();
|
||||||
throw new InvalidParameterSpecException(
|
throw new InvalidParameterSpecException(
|
||||||
"Parameter spec has class " + paramSpecClass.getName());
|
"Mozilla-JSS IvParameter spec class error"
|
||||||
|
+ paramSpecClass.getName());
|
||||||
}
|
}
|
||||||
return ivParamSpec;
|
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.TokenException;
|
||||||
import org.mozilla.jss.crypto.SecretKeyFacade;
|
import org.mozilla.jss.crypto.SecretKeyFacade;
|
||||||
import org.mozilla.jss.crypto.TokenRuntimeException;
|
import org.mozilla.jss.crypto.TokenRuntimeException;
|
||||||
import org.mozilla.jss.crypto.JSSSecureRandom;
|
|
||||||
import org.mozilla.jss.CryptoManager;
|
import org.mozilla.jss.CryptoManager;
|
||||||
import org.mozilla.jss.util.Assert;
|
import org.mozilla.jss.util.Assert;
|
||||||
import org.mozilla.jss.pkcs11.PK11SecureRandom;
|
|
||||||
import org.mozilla.jss.pkcs11.PK11PubKey;
|
import org.mozilla.jss.pkcs11.PK11PubKey;
|
||||||
import org.mozilla.jss.pkcs11.PK11PrivKey;
|
import org.mozilla.jss.pkcs11.PK11PrivKey;
|
||||||
import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
|
import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
|
||||||
import org.mozilla.jss.asn1.ASN1Util;
|
import org.mozilla.jss.asn1.ASN1Util;
|
||||||
import org.mozilla.jss.asn1.BIT_STRING;
|
import org.mozilla.jss.asn1.BIT_STRING;
|
||||||
import org.mozilla.jss.asn1.InvalidBERException;
|
import org.mozilla.jss.asn1.InvalidBERException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
class JSSCipherSpi extends javax.crypto.CipherSpi {
|
class JSSCipherSpi extends javax.crypto.CipherSpi {
|
||||||
private String algFamily=null;
|
private String algFamily=null;
|
||||||
|
@ -82,6 +82,8 @@ class JSSCipherSpi extends javax.crypto.CipherSpi {
|
||||||
private KeyWrapAlgorithm wrapAlg = null;
|
private KeyWrapAlgorithm wrapAlg = null;
|
||||||
private AlgorithmParameterSpec params = null;
|
private AlgorithmParameterSpec params = null;
|
||||||
private int blockSize;
|
private int blockSize;
|
||||||
|
//keyStrength is used for RC2ParameterSpec and EncryptionAlgorithm.lookup
|
||||||
|
private int keyStrength;
|
||||||
|
|
||||||
private JSSCipherSpi() { }
|
private JSSCipherSpi() { }
|
||||||
|
|
||||||
|
@ -128,7 +130,6 @@ class JSSCipherSpi extends javax.crypto.CipherSpi {
|
||||||
throws InvalidKeyException, InvalidAlgorithmParameterException
|
throws InvalidKeyException, InvalidAlgorithmParameterException
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// throw away any previous state
|
// throw away any previous state
|
||||||
cipher = null;
|
cipher = null;
|
||||||
wrapper = null;
|
wrapper = null;
|
||||||
|
@ -162,10 +163,17 @@ class JSSCipherSpi extends javax.crypto.CipherSpi {
|
||||||
SymmetricKey symkey = ((SecretKeyFacade)key).key;
|
SymmetricKey symkey = ((SecretKeyFacade)key).key;
|
||||||
|
|
||||||
// lookup the encryption algorithm
|
// lookup the encryption algorithm
|
||||||
int keyStrength = symkey.getStrength();
|
keyStrength = symkey.getStrength();
|
||||||
encAlg = EncryptionAlgorithm.lookup(algFamily, algMode,
|
encAlg = EncryptionAlgorithm.lookup(algFamily, algMode,
|
||||||
algPadding, keyStrength);
|
algPadding, keyStrength);
|
||||||
blockSize = encAlg.getBlockSize();
|
blockSize = encAlg.getBlockSize();
|
||||||
|
|
||||||
|
if( !token.doesAlgorithm(encAlg) ) {
|
||||||
|
throw new NoSuchAlgorithmException(
|
||||||
|
encAlg.toString() + " is not supported by this token " +
|
||||||
|
token.getName());
|
||||||
|
}
|
||||||
|
|
||||||
cipher = token.getCipherContext(encAlg);
|
cipher = token.getCipherContext(encAlg);
|
||||||
|
|
||||||
if( opmode == Cipher.ENCRYPT_MODE ) {
|
if( opmode == Cipher.ENCRYPT_MODE ) {
|
||||||
|
@ -236,8 +244,21 @@ class JSSCipherSpi extends javax.crypto.CipherSpi {
|
||||||
throws InvalidKeyException, InvalidAlgorithmParameterException
|
throws InvalidKeyException, InvalidAlgorithmParameterException
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
engineInit(opmode, key, givenParams.getParameterSpec(null), random);
|
AlgorithmParameterSpec gp = null;
|
||||||
} catch(InvalidParameterSpecException e) {
|
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());
|
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 {
|
generateAlgParams(Algorithm alg, int blockSize) throws InvalidKeyException {
|
||||||
Class paramClass = alg.getParameterClass();
|
Class [] paramClasses = alg.getParameterClasses();
|
||||||
|
AlgorithmParameterSpec algParSpec = null;
|
||||||
if( paramClass == null ) {
|
if( paramClasses == null ) {
|
||||||
// no parameters are needed
|
// no parameters are needed
|
||||||
return null;
|
return null;
|
||||||
} else if( paramClass.equals( IvParameterSpec.class ) ) {
|
}
|
||||||
// generate an IV
|
// generate an IV
|
||||||
byte[] iv = new byte[blockSize];
|
byte[] iv = new byte[blockSize];
|
||||||
PK11SecureRandom rng = new PK11SecureRandom();
|
try {
|
||||||
rng.nextBytes(iv);
|
SecureRandom random = SecureRandom.getInstance("pkcs11prng",
|
||||||
return new IvParameterSpec(iv);
|
"Mozilla-JSS");
|
||||||
} else {
|
random.nextBytes(iv);
|
||||||
// I don't know any other parameter types.
|
} catch (Exception e) {
|
||||||
throw new InvalidKeyException(
|
Assert.notReached(e.getMessage());
|
||||||
"Unable to generate parameters of type " +paramClass.getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 { }
|
private static class NoAlgParams implements AlgorithmParameterSpec { }
|
||||||
|
@ -293,22 +325,19 @@ class JSSCipherSpi extends javax.crypto.CipherSpi {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AlgorithmParameters engineGetParameters() {
|
public AlgorithmParameters engineGetParameters() {
|
||||||
if( params instanceof IvParameterSpec ) {
|
AlgorithmParameters algParams = null;
|
||||||
try {
|
try {
|
||||||
AlgorithmParameters algParams =
|
if(( params instanceof IvParameterSpec )
|
||||||
AlgorithmParameters.getInstance("IvAlgorithmParameters",
|
|| ( params instanceof RC2ParameterSpec )) {
|
||||||
"Mozilla-JSS");
|
algParams = AlgorithmParameters.getInstance(algFamily);
|
||||||
algParams.init(params);
|
algParams.init(params);
|
||||||
return algParams;
|
}
|
||||||
} catch(NoSuchAlgorithmException nsae) {
|
} catch(NoSuchAlgorithmException nsae) {
|
||||||
Assert.notReached(nsae.getMessage());
|
Assert.notReached(nsae.getMessage());
|
||||||
} catch( NoSuchProviderException nspe) {
|
|
||||||
Assert.notReached(nspe.getMessage());
|
|
||||||
} catch(InvalidParameterSpecException ipse) {
|
} catch(InvalidParameterSpecException ipse) {
|
||||||
Assert.notReached(ipse.getMessage());
|
Assert.notReached(ipse.getMessage());
|
||||||
}
|
}
|
||||||
}
|
return algParams;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int engineGetOutputSize(int inputLen) {
|
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,122 +41,360 @@ import org.mozilla.jss.CryptoManager;
|
||||||
import org.mozilla.jss.util.Assert;
|
import org.mozilla.jss.util.Assert;
|
||||||
import org.mozilla.jss.util.Password;
|
import org.mozilla.jss.util.Password;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
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 {
|
public class SymKeyGen {
|
||||||
|
private CryptoToken token = null;
|
||||||
|
byte[] plainText16Bytes = "Firefox rules!".getBytes(); /* 16 bytes */
|
||||||
|
byte[] plainText18Bytes = "Thunderbird rules!".getBytes(); /* 18 bytes */
|
||||||
|
|
||||||
|
public SymmetricKey genPBEKey(PBEAlgorithm alg,
|
||||||
|
SymmetricKey.Type keyType, int keyStrength)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
public static void main(String args[]) {
|
SymmetricKey key = null;
|
||||||
|
byte[] keyData;
|
||||||
|
KeyGenerator kg = token.getKeyGenerator(alg);
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
CryptoManager.initialize(".");
|
|
||||||
CryptoManager cm = CryptoManager.getInstance();
|
|
||||||
CryptoToken token = cm.getInternalCryptoToken();
|
|
||||||
byte[] keyData;
|
|
||||||
|
|
||||||
// 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 {
|
try {
|
||||||
kg.initialize(56);
|
//this is debug code you don't initialize
|
||||||
throw new Exception("ERROR: Initializing PBE key with strength "+
|
//PBE algs with key Strength doing this should throw
|
||||||
"succeeded");
|
//InvaldAlgortithmParameterException
|
||||||
} catch( InvalidAlgorithmParameterException e) { }
|
kg.initialize(keyStrength);
|
||||||
Password pass = new Password( ("passwd").toCharArray() );
|
throw new Exception("ERROR: Initializing PBE key with strength " +
|
||||||
byte[] salt = new byte[] { (byte)0xff, (byte)0x00, (byte)0xff };
|
keyStrength + " succeeded");
|
||||||
|
|
||||||
|
} catch( InvalidAlgorithmParameterException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Password pass = new Password( ("passwd1").toCharArray() );
|
||||||
|
byte[] salt = genSalt(alg.getSaltLength());
|
||||||
PBEKeyGenParams kgp = new PBEKeyGenParams(pass, salt, 2);
|
PBEKeyGenParams kgp = new PBEKeyGenParams(pass, salt, 2);
|
||||||
kg.initialize(kgp);
|
kg.initialize(kgp);
|
||||||
key = kg.generate();
|
key = kg.generate();
|
||||||
if( key.getType() != SymmetricKey.DES ) {
|
|
||||||
|
if( key.getType() != keyType ) {
|
||||||
throw new Exception("Wrong key type: "+key.getType());
|
throw new Exception("Wrong key type: "+key.getType());
|
||||||
}
|
}
|
||||||
if( ! key.getOwningToken().equals( token ) ) {
|
if( ! key.getOwningToken().equals( token ) ) {
|
||||||
throw new Exception("wrong token");
|
throw new Exception("wrong token");
|
||||||
}
|
}
|
||||||
if( key.getStrength() != 56 && key.getStrength() != 64) {
|
if( key.getStrength() != keyStrength ) {
|
||||||
throw new Exception("wrong strength: "+key.getStrength());
|
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();
|
keyData = key.getKeyData();
|
||||||
if( keyData.length != 8 ) {
|
if( keyData.length != keyLength ) {
|
||||||
throw new Exception("key data wrong length: " + keyData.length);
|
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) {
|
} catch(Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -419,6 +419,24 @@ $result >>=8;
|
||||||
$result and print "Disable FIPSMODE returned $result\n";
|
$result and print "Disable FIPSMODE returned $result\n";
|
||||||
print_case_result ($result,"FIPSMODE disabled");
|
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;
|
$portJSSEServer=$portJSSEServer+1;
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
Загрузка…
Ссылка в новой задаче