Wednesday, February 24, 2010
Sunday, February 14, 2010
The RichRSACipher class: An RSA cipher implementation
The RichRSACipher class: An RSA cipher implementation
package com.richware.chap12;
import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
import javax.crypto.*;
import sun.misc.*;
/**
* Class RichRSACipher
* Description: This is an example of a
* simple RSA Encryption
* RSA information is from PKCS#1v2.0
* a publication from RSA Security
*
* Copyright: Copyright (c) 2002 Wiley Publishing, Inc.
* @author Rich Helton
* @version 1.0
* DISCLAIMER: Please refer to the disclaimer at the beginning of this book.
*/
public final class RichRSACipher extends CipherSpi
{
private RSAKeyGenParameterSpec params_;
private SecureRandom random_;
private final static boolean DEBUG = true;
private int opmode_;
private Key key_;
private byte[] internal_buffer_;
/**
* Constructor RichRSACipher
*/
public RichRSACipher() {}
/**
* Method engineDoFinal
* Description: See CipherSpi
*/
protected byte[] engineDoFinal(
byte[] input, int inputOffset, int inputLen)
throws IllegalBlockSizeException,
BadPaddingException
{
byte[] output = engineUpdate(input, inputOffset, inputLen);
internal_buffer_ = null;
return output;
}
/**
* Method engineDoFinal
* Description: See CipherSpi
*/
protected int engineDoFinal(
byte[] input, int inputOffset, int inputLen, byte[] output,
int outputOffset)
throws ShortBufferException,
IllegalBlockSizeException,
BadPaddingException
{
byte[] buffer;
buffer = engineDoFinal(input, inputOffset, inputLen);
if (output.length - outputOffset < buffer.length)
{
throw new ShortBufferException(
"Output longer than buffer");
}
System.arraycopy(buffer, 0, output, outputOffset,
buffer.length);
return buffer.length;
}
/**
* Method engineGetBlockSize
* Description: See CipherSpi
*/
protected int engineGetBlockSize()
{
if ((opmode_ == Cipher.ENCRYPT_MODE)
|| (opmode_ == Cipher.WRAP_MODE))
{
return params_.getKeysize();
}
else
{
return params_.getKeysize() - 1;
}
}
/**
* Method engineGetIV
* Description: See CipherSpi
*/
protected byte[] engineGetIV()
{
return null; // If not supported
}
/**
* Method engineGetKeySize
* Description: See CipherSpi
*/
protected int engineGetKeySize(Key key)
throws InvalidKeyException
{
/*
* Get the key size based on bit length
*/
if (key instanceof RSAPrivateKey)
{
RSAPrivateKey k = (RSAPrivateKey) key;
return k.getModulus().bitLength();
}
else if (key instanceof RSAPublicKey)
{
RSAPublicKey k = (RSAPublicKey) key;
return k.getModulus().bitLength();
}
throw new InvalidKeyException("Unsupported RSA key!");
}
/**
* Method engineGetOutputSize
* Description: See CipherSpi
*/
protected int engineGetOutputSize(int inputLen)
{
if ((opmode_ == Cipher.ENCRYPT_MODE)
|| (opmode_ == Cipher.WRAP_MODE))
{
return params_.getKeysize();
}
else
{
return params_.getKeysize() - 1;
}
}
/**
* Method engineGetParameters
* Description: See CipherSpi
*/
protected AlgorithmParameters engineGetParameters()
{
return null;
}
/**
* Method engineInit
* Description: See CipherSpi
*/
protected void engineInit(
int opmode, Key _key, AlgorithmParameterSpec params, SecureRandom
_random)
throws InvalidKeyException,
InvalidAlgorithmParameterException
{
// Check for valid key
if ((!(_key instanceof RSAPublicKey))
&& (!(_key instanceof RSAPrivateKey)))
{
throw new InvalidKeyException("Unsupported RSA Key!");
}
// Check for valid Parameter Spec
if ((params != null)
&& (!(params instanceof RSAKeyGenParameterSpec)))
{
throw new InvalidAlgorithmParameterException(
"Unsupported RSA AlgorithmParameterSpec!");
}
// Initialize the params
if (params != null)
{
params_ = (RSAKeyGenParameterSpec) params;
}
else
{
int keysize = 0;
BigInteger publicExp = null;
if (_key instanceof RSAPublicKey)
{
publicExp = ((RSAPublicKey) _key).getPublicExponent();
int modulusLength =
((RSAPublicKey) _key).getModulus().bitLength();
keysize = (modulusLength + 7) / 8;
}
else if (_key instanceof RSAPrivateKey)
{
int modulusLength =
((RSAPrivateKey) _key).getModulus().bitLength();
keysize = (modulusLength + 7) / 8;
}
if(DEBUG){
System.out.println("RichRSACipher:engineInit:keysize:" + keysize);
}
params_ = new RSAKeyGenParameterSpec(keysize, publicExp);
}
random_ = _random;
// Check for valid types of opmode
if ((opmode == Cipher.DECRYPT_MODE)
|| (opmode == Cipher.ENCRYPT_MODE)
|| (opmode == Cipher.UNWRAP_MODE)
|| (opmode == Cipher.WRAP_MODE))
{
if (((opmode == Cipher.DECRYPT_MODE) || (opmode == Cipher
.UNWRAP_MODE)) && (_key instanceof RSAPublicKey))
{
throw new InvalidKeyException(
"Unsupported: Decrypt/UnWrap mode must use RSAPrivateKey");
}
if (((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher
.WRAP_MODE)) && (_key instanceof RSAPrivateKey))
{
throw new InvalidKeyException(
"Unsupported: Encrypt/Wrap mode must use RSAPublicKey");
}
if(DEBUG){
if ((opmode == Cipher.DECRYPT_MODE) || (opmode == Cipher.UNWRAP_MODE)){
System.out.println("RichRSACipher:engineInit:DECRYPT_MODE");
}else{
System.out.println("RichRSACipher:engineInit:ENCRYPT_MODE");
}
}
}
else
{
throw new InvalidKeyException("Unsupported opmode!");
}
opmode_ = opmode;
key_ = _key;
}
/**
* Method engineInit
* Description: See CipherSpi
*/
protected void engineInit(
int opmode, Key _key, AlgorithmParameters params, SecureRandom _random)
throws InvalidKeyException,
InvalidAlgorithmParameterException
{
/*
* Note _key is used instead of Key, because Key is a class.
* Random is also a class.
*/
engineInit(opmode, _key, (AlgorithmParameterSpec) null,
_random);
}
/**
* Method engineInit
* Description: See CipherSpi
*/
protected void engineInit(
int opmode, Key _key, SecureRandom _random)
throws InvalidKeyException
{
try
{
engineInit(opmode, _key, (AlgorithmParameterSpec) null,
_random);
}
catch (InvalidAlgorithmParameterException ex)
{
throw new InvalidKeyException(ex.getMessage());
}
}
/**
* Method engineSetMode
* Description: See CipherSpi
*/
protected void engineSetMode(String mode)
throws NoSuchAlgorithmException
{
if (!mode.equalsIgnoreCase("ECB"))
{
throw new NoSuchAlgorithmException(
"RSA supports only ECB mode");
}
}
/**
* Method engineSetPadding
* Description: See CipherSpi
*/
protected void engineSetPadding(String s)
throws NoSuchPaddingException
{
// Only accepts avaliable padding
if (!s.equalsIgnoreCase("PKCS1_V1_5"))
{
throw new NoSuchPaddingException("Unknown padding: "
+ s);
}
}
/**
* Method engineUpdate
* Description: See CipherSpi
*/
protected byte[] engineUpdate(byte[] input, int inputOffset,
int inputLen)
{
try
{
if (inputOffset > 0)
{
int outputSize = inputOffset + inputLen;
byte[] tmp = new byte[outputSize];
System.arraycopy(input, inputOffset, internal_buffer_,
internal_buffer_.length, inputLen);
if ((opmode_ == Cipher.ENCRYPT_MODE)
|| (opmode_ == Cipher.WRAP_MODE))
{
return (encrypt(internal_buffer_));
}
else
{
return (decrypt(internal_buffer_));
}
}
else
{
internal_buffer_ = new byte[inputLen];
System.arraycopy(input, 0, internal_buffer_,0, inputLen);
if ((opmode_ == Cipher.ENCRYPT_MODE)
|| (opmode_ == Cipher.WRAP_MODE))
{
if(DEBUG){
System.out.println("RichRSACipher:engineUpdate:encrypting");
}
return (encrypt(internal_buffer_));
}
else
{
if(DEBUG){
System.out.println("RichRSACipher:engineUpdate:decrypting");
}
return (decrypt(internal_buffer_));
}
}
}
/*
* Catches
*/
catch (Exception ex)
{
ex.printStackTrace();
}
return null;
}
/**
* Method engineUpdate
* Description: See CipherSpi
*/
protected int engineUpdate(
byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset)
throws ShortBufferException
{
byte[] buffer;
buffer = engineUpdate(input, inputOffset, inputLen);
if (output.length - outputOffset < buffer.length)
{
throw new ShortBufferException(
"Output longer than buffer");
}
System.arraycopy(buffer, 0, output, outputOffset,
buffer.length);
return buffer.length;
}
/**
* Method I2OSP
* Description: Integer to Octet String Primitive
* See PKCS#1
*/
private byte[] I2OSP(BigInteger x, int l)
throws IllegalBlockSizeException
{
/*
* Section 4.1 of PKCS#1v2.0
* I2OSP converts a nonnegative integer to an octet string
* of a specified length. I2OSP (x, l)
* Input: x nonnegative integer to be converted
* l intended length of the resulting octet string
* Output: X corresponding octet string of length l; or
* integer too large
* Steps:
*/
/*
* 1. If x = 256l, output "integer too large " and stop.
*/
int j = (x.bitLength() + 7) / 8;
if (l == -1)
{
l = j;
}
if ((j > l) || (x.signum() == -1))
{
throw new IllegalBlockSizeException("Block too large");
}
/*
* 2. Write the integer x in its unique l-digit representation
* base 256: x = xl- 1 256^ (l- 1) + xl -2 256 256^(l -2) + ...& +
x1 256 + x0
* where 0 = xi < 256 (note that one or more leading digits
* will be zero if x < 256^ (l- 1)).
*/
byte[] C = x.toByteArray();
/*
* remove the leading zeros
*/
int index = 0;
for (; (index < C.length) && (C[index] == 0); index++);
if (index > 0)
{
byte[] temp = new byte[C.length - index];
System.arraycopy(C, index, temp, 0, temp.length);
C = temp;
}
else if (C.length > l)
{
throw new IllegalBlockSizeException("Block too large");
}
/*
* 3. Let the octet Xi have the value xl -i for 1 = i = l.
* Output the octet string X = X1 X2 & ... Xl.
*/
if (C.length == l)
{
return C;
}
/*
* C is not long enough
*/
byte[] result = new byte[l];
System.arraycopy(C, 0, result, l - C.length, C.length);
return result;
}
/**
* Method encrypt
* Description: Encrypt with pad
* See PKCS#1
* @param M the plaintext message
*/
private byte[] encrypt(byte[] M)
throws IllegalBlockSizeException
{
/*
* RSA Steps according to PKCS #1 v 2.0 pg 15 for encryption:
* 1. Apply the EME-PKCS1-v1_5 encoding operation (Section 9.1.2.1)
* to the message M to produce an encoded message EM of length k-1
* octets: EM = EME-PKCS1-V1_5-ENCODE (M, k-1)
* If the encoding operation outputs "message too long, ," then
output
* message too long and stop.
*/
int k = params_.getKeysize();
byte[] EM = EME_PKCS1_V1_5_ENCODE(M, k - 1);
/*
* 2. Convert the encoded message EM to an integer message
* representative m: m = OS2IP (EM)
*/
BigInteger m = new BigInteger(1, EM);
/*
* 3. Apply the RSAEP encryption primitive (Section 5.1.1) to the
* public key (n, e) and the message representative m to produce
* an integer ciphertext representative c: c = RSAEP ((n, e), m)
*/
BigInteger c = RSAEP((RSAPublicKey) key_, m);
/*
* 4. Convert the ciphertext representative c to a ciphertext C of
* length k octets: C = I2OSP (c, k)
*/
byte[] C = I2OSP(c, k);
/*
* 5. Output the ciphertext C.
*/
return C;
}
/**
* Method decrypt
* Description: Decrypt with pad
* See PKCS#1
* @param M the ciphertext message
*/
private byte[] decrypt(byte[] C)
throws BadPaddingException, IllegalBlockSizeException
{
/*
* RSA Steps according to PKCS #1 v 2.0 pg 16 for decryption:
* 1. If the length of the ciphertext C is not k octets, output
* decryption error and stop.
*/
int k = params_.getKeysize();
if (k != C.length)
{
throw new IllegalBlockSizeException("decryption error");
}
/*
* 2. Convert the ciphertext C to an integer ciphertext
* representative c: c = OS2IP (C)
*/
BigInteger c = new BigInteger(1, C);
/*
* 3. Apply the RSADP decryption primitive to the private
* key (n, d) and the ciphertext representative c to produce
* an integer message representative m: m = RSADP ((n, d), c)
* If RSADP outputs ciphertext out of range, then output
* decryption error and stop.
*/
BigInteger m = RSADP((RSAPrivateKey) key_, c);
/*
* 4. Convert the message representative m to an encoded message
* EM of length k-1 octets: EM = I2OSP (m, k-1)
* If I2OSP outputs integer too large, then output decryption
* error and stop.
*/
byte[] EM = I2OSP(m, k - 1);
/*
* 5. Apply the EME-PKCS1-v1_5 decoding operation to the encoded
* message EM to recover a message M: M = EME-PKCS1-V1_5-DECODE(EM)
* If the decoding operation outputs decoding error, then output
* decryption error and stop.
*/
byte[] M = EME_PKCS1_V1_5_DECODE(EM);
/*
* 6. Output the message M.
*/
return M;
}
/**
* Method EME_PKCS1_V1_5_ENCODE
* Description: Pad encoding
*
* @param M the ciphertext message
* @param emLen the length of encr message
*
* @return encoded pad
*
* @throws IllegalBlockSizeException
*
*/
private byte[] EME_PKCS1_V1_5_ENCODE(byte[] M, int emLen)
throws IllegalBlockSizeException
{
/*
* Section 9.1.2.1 of PKCS#1v2.0
* 1. If the length of the message M is greater than emLen 10
* octets, output message too long and stop.
*/
if (M.length > emLen - 10)
{
throw new IllegalBlockSizeException("message too long");
}
/*
* 2. Generate an octet string PS of length emLen-||M||-2
* consisting of pseudorandomly generated nonzero octets.
* The length of PS will be at least 8 octets.
*/
byte[] PS =
new byte[(emLen - M.length - 2)];
// Fill the padding string with random non-zero bytes
for (int i = 0; i < PS.length; i++)
{
PS[i] = (byte) (random_.nextInt(255) + 1);
}
/*
* 3. Concatenate PS, the message M, and other padding to
* form the encoded message EM as EM = 02 || PS || 00 || M
*/
byte[] EM = new byte[emLen];
int index = 0;
EM[index++] = (byte) 0x02;
for (int i = 0; i < PS.length; i++)
{
EM[index++] = PS[i];
}
EM[index++] = (byte) 0x00;
for (int i = 0; i < M.length; i++)
{
EM[index++] = M[i];
}
/*
* 4. Output EM.
*/
return EM;
}
/**
* Method EME_PKCS1_V1_5_DECODE
* Description: Pad decoding
*
* @param EM the encrypted message
*
* @return pad
*
* @throws BadPaddingException
*
*/
private byte[] EME_PKCS1_V1_5_DECODE(byte[] EM)
throws BadPaddingException
{
/*
* Section 9.1.2.2 of PKCS#1v2.0
* 1. If the length of the encoded
* message EM is less than 10, output decoding error
* and stop.
*/
if (EM.length < 10)
{
throw new BadPaddingException("message too short");
}
/*
* 2. Separate the encoded message EM into an octet string PS
* consisting of nonzero octets and a message M as
* EM = 02 || PS || 00 || M. If the first octet of EM is not 02,
* or if there is no 00 octet to separate PS from M,
* output decoding error and stop.
*/
if (EM[0] != (byte) 0x02)
{
throw new BadPaddingException(
"message not formatted properly");
}
// Need to start by looking for the first non-zero byte
int start = 0;
while (EM[start] != (byte) 0x00)
{
start++;
if (start >= EM.length)
{
throw new BadPaddingException("bad padding");
}
}
start++; // Ignore the first 00
/*
* 3. If the length of PS is less than 8 octets,
* output decoding error and stop.
*/
if (start < 10)
{
throw new BadPaddingException("bad padding");
}
byte[] M = new byte[EM.length - start];
System.arraycopy(EM, start, M, 0, M.length);
/*
* 4. Output M.
*/
return M;
}
/**
* Method RSEAP
* Description: Performs the encryyrption
*
* @param publicKey the RSA public key
* @param m the plaintext integer
*
* @return the ciphertext integer
*
* @throws IllegalBlockSizeException
*
*/
private BigInteger RSAEP(RSAPublicKey publicKey, BigInteger m)
throws IllegalBlockSizeException
{
/*
* RSAEP ((n, e), m)
* Input: (n, e) RSA public key
* m message representative, an integer between 0 and n-1
* Output: c ciphertext representative, an integer between 0 and
* n-1; or message representative out of range
* Assumptions: public key (n, e) is valid
*/
BigInteger e = publicKey.getPublicExponent();
BigInteger n = publicKey.getModulus();
/*
* 1. If the message representative m is not between 0 and n-1,
* output message representative out of range and stop.
*/
BigInteger nMinusOne = n.subtract(BigInteger.ONE);
/*
* m > 0 and m < n-1
*/
if (m.compareTo(BigInteger.ZERO) < 0)
{
throw new IllegalBlockSizeException(
"Ciphertext too small");
}
if (m.compareTo(nMinusOne) > 0)
{
throw new IllegalBlockSizeException(
"Ciphertext too large");
}
/*
* 2. Let c = me mod n.
*/
BigInteger c = m.modPow(e, n);
/*
* 3. Output c.
*/
return c;
}
/**
* Method RSADP
* Description: Performs the decryption
*
* @param K the RSA Private Key
* @param c an integer representing
* the cipher
*
* @return the plaintext integer
*
*/
private BigInteger RSADP(RSAPrivateKey K,
BigInteger c)
{
/*
* RSADP (K, c)
* Input: K RSA private key, where K has one of the following
* forms: a pair (n, d)
* a quintuple (p, q, dP, dQ, qInv)
* c ciphertext representative, an integer between 0 and n-1
* Output: m message representative, an integer between 0 and n-1;
or
* ciphertext representative out of range
* Assumptions: private key K is valid
* Steps:
* 1. If the ciphertext representative c is not between 0 and n-1,
* output ciphertext representative out of range and stop.
*/
/*
* 2.1 Let m = cd mod n.
* PKCS #1 V2.0: RSA CRYPTOGRAPHY STANDARD 9
* Else, if the second form (p, q, dP, dQ, qInv) of K is used:
*/
if (!(K instanceof RSAPrivateCrtKey))
{
BigInteger d = K.getPrivateExponent();
BigInteger n = K.getModulus();
BigInteger m = c.modPow(d, n);
return m;
}
/*
* 2. If the first form (n, d) of K is used:
*/
RSAPrivateCrtKey privateCrtKey =
(RSAPrivateCrtKey) K;
BigInteger p = privateCrtKey.getPrimeP();
BigInteger q = privateCrtKey.getPrimeQ();
BigInteger dP =
privateCrtKey.getPrimeExponentP();
BigInteger dQ =
privateCrtKey.getPrimeExponentQ();
BigInteger qInv =
privateCrtKey.getCrtCoefficient();
/*
* 2.2 Let m1 = cdP mod p.
*/
BigInteger m1 = c.modPow(dP, p);
/*
* 2.3 Let m2 = cdQ mod q.
*/
BigInteger m2 = c.modPow(dQ, q);
/*
* 2.4 Let h = qInv ( m1 m2 ) mod p.
*/
BigInteger h = m1.subtract(m2);
h = h.multiply(qInv);
h = h.mod(p);
/*
* 2.5 Let m = m2 + h q.
*/
BigInteger m = h.multiply(q);
m = m.add(m2);
/*
* 3. Output m.
*/
return m;
}
}
package com.richware.chap12;
import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
import javax.crypto.*;
import sun.misc.*;
/**
* Class RichRSACipher
* Description: This is an example of a
* simple RSA Encryption
* RSA information is from PKCS#1v2.0
* a publication from RSA Security
*
* Copyright: Copyright (c) 2002 Wiley Publishing, Inc.
* @author Rich Helton
* @version 1.0
* DISCLAIMER: Please refer to the disclaimer at the beginning of this book.
*/
public final class RichRSACipher extends CipherSpi
{
private RSAKeyGenParameterSpec params_;
private SecureRandom random_;
private final static boolean DEBUG = true;
private int opmode_;
private Key key_;
private byte[] internal_buffer_;
/**
* Constructor RichRSACipher
*/
public RichRSACipher() {}
/**
* Method engineDoFinal
* Description: See CipherSpi
*/
protected byte[] engineDoFinal(
byte[] input, int inputOffset, int inputLen)
throws IllegalBlockSizeException,
BadPaddingException
{
byte[] output = engineUpdate(input, inputOffset, inputLen);
internal_buffer_ = null;
return output;
}
/**
* Method engineDoFinal
* Description: See CipherSpi
*/
protected int engineDoFinal(
byte[] input, int inputOffset, int inputLen, byte[] output,
int outputOffset)
throws ShortBufferException,
IllegalBlockSizeException,
BadPaddingException
{
byte[] buffer;
buffer = engineDoFinal(input, inputOffset, inputLen);
if (output.length - outputOffset < buffer.length)
{
throw new ShortBufferException(
"Output longer than buffer");
}
System.arraycopy(buffer, 0, output, outputOffset,
buffer.length);
return buffer.length;
}
/**
* Method engineGetBlockSize
* Description: See CipherSpi
*/
protected int engineGetBlockSize()
{
if ((opmode_ == Cipher.ENCRYPT_MODE)
|| (opmode_ == Cipher.WRAP_MODE))
{
return params_.getKeysize();
}
else
{
return params_.getKeysize() - 1;
}
}
/**
* Method engineGetIV
* Description: See CipherSpi
*/
protected byte[] engineGetIV()
{
return null; // If not supported
}
/**
* Method engineGetKeySize
* Description: See CipherSpi
*/
protected int engineGetKeySize(Key key)
throws InvalidKeyException
{
/*
* Get the key size based on bit length
*/
if (key instanceof RSAPrivateKey)
{
RSAPrivateKey k = (RSAPrivateKey) key;
return k.getModulus().bitLength();
}
else if (key instanceof RSAPublicKey)
{
RSAPublicKey k = (RSAPublicKey) key;
return k.getModulus().bitLength();
}
throw new InvalidKeyException("Unsupported RSA key!");
}
/**
* Method engineGetOutputSize
* Description: See CipherSpi
*/
protected int engineGetOutputSize(int inputLen)
{
if ((opmode_ == Cipher.ENCRYPT_MODE)
|| (opmode_ == Cipher.WRAP_MODE))
{
return params_.getKeysize();
}
else
{
return params_.getKeysize() - 1;
}
}
/**
* Method engineGetParameters
* Description: See CipherSpi
*/
protected AlgorithmParameters engineGetParameters()
{
return null;
}
/**
* Method engineInit
* Description: See CipherSpi
*/
protected void engineInit(
int opmode, Key _key, AlgorithmParameterSpec params, SecureRandom
_random)
throws InvalidKeyException,
InvalidAlgorithmParameterException
{
// Check for valid key
if ((!(_key instanceof RSAPublicKey))
&& (!(_key instanceof RSAPrivateKey)))
{
throw new InvalidKeyException("Unsupported RSA Key!");
}
// Check for valid Parameter Spec
if ((params != null)
&& (!(params instanceof RSAKeyGenParameterSpec)))
{
throw new InvalidAlgorithmParameterException(
"Unsupported RSA AlgorithmParameterSpec!");
}
// Initialize the params
if (params != null)
{
params_ = (RSAKeyGenParameterSpec) params;
}
else
{
int keysize = 0;
BigInteger publicExp = null;
if (_key instanceof RSAPublicKey)
{
publicExp = ((RSAPublicKey) _key).getPublicExponent();
int modulusLength =
((RSAPublicKey) _key).getModulus().bitLength();
keysize = (modulusLength + 7) / 8;
}
else if (_key instanceof RSAPrivateKey)
{
int modulusLength =
((RSAPrivateKey) _key).getModulus().bitLength();
keysize = (modulusLength + 7) / 8;
}
if(DEBUG){
System.out.println("RichRSACipher:engineInit:keysize:" + keysize);
}
params_ = new RSAKeyGenParameterSpec(keysize, publicExp);
}
random_ = _random;
// Check for valid types of opmode
if ((opmode == Cipher.DECRYPT_MODE)
|| (opmode == Cipher.ENCRYPT_MODE)
|| (opmode == Cipher.UNWRAP_MODE)
|| (opmode == Cipher.WRAP_MODE))
{
if (((opmode == Cipher.DECRYPT_MODE) || (opmode == Cipher
.UNWRAP_MODE)) && (_key instanceof RSAPublicKey))
{
throw new InvalidKeyException(
"Unsupported: Decrypt/UnWrap mode must use RSAPrivateKey");
}
if (((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher
.WRAP_MODE)) && (_key instanceof RSAPrivateKey))
{
throw new InvalidKeyException(
"Unsupported: Encrypt/Wrap mode must use RSAPublicKey");
}
if(DEBUG){
if ((opmode == Cipher.DECRYPT_MODE) || (opmode == Cipher.UNWRAP_MODE)){
System.out.println("RichRSACipher:engineInit:DECRYPT_MODE");
}else{
System.out.println("RichRSACipher:engineInit:ENCRYPT_MODE");
}
}
}
else
{
throw new InvalidKeyException("Unsupported opmode!");
}
opmode_ = opmode;
key_ = _key;
}
/**
* Method engineInit
* Description: See CipherSpi
*/
protected void engineInit(
int opmode, Key _key, AlgorithmParameters params, SecureRandom _random)
throws InvalidKeyException,
InvalidAlgorithmParameterException
{
/*
* Note _key is used instead of Key, because Key is a class.
* Random is also a class.
*/
engineInit(opmode, _key, (AlgorithmParameterSpec) null,
_random);
}
/**
* Method engineInit
* Description: See CipherSpi
*/
protected void engineInit(
int opmode, Key _key, SecureRandom _random)
throws InvalidKeyException
{
try
{
engineInit(opmode, _key, (AlgorithmParameterSpec) null,
_random);
}
catch (InvalidAlgorithmParameterException ex)
{
throw new InvalidKeyException(ex.getMessage());
}
}
/**
* Method engineSetMode
* Description: See CipherSpi
*/
protected void engineSetMode(String mode)
throws NoSuchAlgorithmException
{
if (!mode.equalsIgnoreCase("ECB"))
{
throw new NoSuchAlgorithmException(
"RSA supports only ECB mode");
}
}
/**
* Method engineSetPadding
* Description: See CipherSpi
*/
protected void engineSetPadding(String s)
throws NoSuchPaddingException
{
// Only accepts avaliable padding
if (!s.equalsIgnoreCase("PKCS1_V1_5"))
{
throw new NoSuchPaddingException("Unknown padding: "
+ s);
}
}
/**
* Method engineUpdate
* Description: See CipherSpi
*/
protected byte[] engineUpdate(byte[] input, int inputOffset,
int inputLen)
{
try
{
if (inputOffset > 0)
{
int outputSize = inputOffset + inputLen;
byte[] tmp = new byte[outputSize];
System.arraycopy(input, inputOffset, internal_buffer_,
internal_buffer_.length, inputLen);
if ((opmode_ == Cipher.ENCRYPT_MODE)
|| (opmode_ == Cipher.WRAP_MODE))
{
return (encrypt(internal_buffer_));
}
else
{
return (decrypt(internal_buffer_));
}
}
else
{
internal_buffer_ = new byte[inputLen];
System.arraycopy(input, 0, internal_buffer_,0, inputLen);
if ((opmode_ == Cipher.ENCRYPT_MODE)
|| (opmode_ == Cipher.WRAP_MODE))
{
if(DEBUG){
System.out.println("RichRSACipher:engineUpdate:encrypting");
}
return (encrypt(internal_buffer_));
}
else
{
if(DEBUG){
System.out.println("RichRSACipher:engineUpdate:decrypting");
}
return (decrypt(internal_buffer_));
}
}
}
/*
* Catches
*/
catch (Exception ex)
{
ex.printStackTrace();
}
return null;
}
/**
* Method engineUpdate
* Description: See CipherSpi
*/
protected int engineUpdate(
byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset)
throws ShortBufferException
{
byte[] buffer;
buffer = engineUpdate(input, inputOffset, inputLen);
if (output.length - outputOffset < buffer.length)
{
throw new ShortBufferException(
"Output longer than buffer");
}
System.arraycopy(buffer, 0, output, outputOffset,
buffer.length);
return buffer.length;
}
/**
* Method I2OSP
* Description: Integer to Octet String Primitive
* See PKCS#1
*/
private byte[] I2OSP(BigInteger x, int l)
throws IllegalBlockSizeException
{
/*
* Section 4.1 of PKCS#1v2.0
* I2OSP converts a nonnegative integer to an octet string
* of a specified length. I2OSP (x, l)
* Input: x nonnegative integer to be converted
* l intended length of the resulting octet string
* Output: X corresponding octet string of length l; or
* integer too large
* Steps:
*/
/*
* 1. If x = 256l, output "integer too large " and stop.
*/
int j = (x.bitLength() + 7) / 8;
if (l == -1)
{
l = j;
}
if ((j > l) || (x.signum() == -1))
{
throw new IllegalBlockSizeException("Block too large");
}
/*
* 2. Write the integer x in its unique l-digit representation
* base 256: x = xl- 1 256^ (l- 1) + xl -2 256 256^(l -2) + ...& +
x1 256 + x0
* where 0 = xi < 256 (note that one or more leading digits
* will be zero if x < 256^ (l- 1)).
*/
byte[] C = x.toByteArray();
/*
* remove the leading zeros
*/
int index = 0;
for (; (index < C.length) && (C[index] == 0); index++);
if (index > 0)
{
byte[] temp = new byte[C.length - index];
System.arraycopy(C, index, temp, 0, temp.length);
C = temp;
}
else if (C.length > l)
{
throw new IllegalBlockSizeException("Block too large");
}
/*
* 3. Let the octet Xi have the value xl -i for 1 = i = l.
* Output the octet string X = X1 X2 & ... Xl.
*/
if (C.length == l)
{
return C;
}
/*
* C is not long enough
*/
byte[] result = new byte[l];
System.arraycopy(C, 0, result, l - C.length, C.length);
return result;
}
/**
* Method encrypt
* Description: Encrypt with pad
* See PKCS#1
* @param M the plaintext message
*/
private byte[] encrypt(byte[] M)
throws IllegalBlockSizeException
{
/*
* RSA Steps according to PKCS #1 v 2.0 pg 15 for encryption:
* 1. Apply the EME-PKCS1-v1_5 encoding operation (Section 9.1.2.1)
* to the message M to produce an encoded message EM of length k-1
* octets: EM = EME-PKCS1-V1_5-ENCODE (M, k-1)
* If the encoding operation outputs "message too long, ," then
output
* message too long and stop.
*/
int k = params_.getKeysize();
byte[] EM = EME_PKCS1_V1_5_ENCODE(M, k - 1);
/*
* 2. Convert the encoded message EM to an integer message
* representative m: m = OS2IP (EM)
*/
BigInteger m = new BigInteger(1, EM);
/*
* 3. Apply the RSAEP encryption primitive (Section 5.1.1) to the
* public key (n, e) and the message representative m to produce
* an integer ciphertext representative c: c = RSAEP ((n, e), m)
*/
BigInteger c = RSAEP((RSAPublicKey) key_, m);
/*
* 4. Convert the ciphertext representative c to a ciphertext C of
* length k octets: C = I2OSP (c, k)
*/
byte[] C = I2OSP(c, k);
/*
* 5. Output the ciphertext C.
*/
return C;
}
/**
* Method decrypt
* Description: Decrypt with pad
* See PKCS#1
* @param M the ciphertext message
*/
private byte[] decrypt(byte[] C)
throws BadPaddingException, IllegalBlockSizeException
{
/*
* RSA Steps according to PKCS #1 v 2.0 pg 16 for decryption:
* 1. If the length of the ciphertext C is not k octets, output
* decryption error and stop.
*/
int k = params_.getKeysize();
if (k != C.length)
{
throw new IllegalBlockSizeException("decryption error");
}
/*
* 2. Convert the ciphertext C to an integer ciphertext
* representative c: c = OS2IP (C)
*/
BigInteger c = new BigInteger(1, C);
/*
* 3. Apply the RSADP decryption primitive to the private
* key (n, d) and the ciphertext representative c to produce
* an integer message representative m: m = RSADP ((n, d), c)
* If RSADP outputs ciphertext out of range, then output
* decryption error and stop.
*/
BigInteger m = RSADP((RSAPrivateKey) key_, c);
/*
* 4. Convert the message representative m to an encoded message
* EM of length k-1 octets: EM = I2OSP (m, k-1)
* If I2OSP outputs integer too large, then output decryption
* error and stop.
*/
byte[] EM = I2OSP(m, k - 1);
/*
* 5. Apply the EME-PKCS1-v1_5 decoding operation to the encoded
* message EM to recover a message M: M = EME-PKCS1-V1_5-DECODE(EM)
* If the decoding operation outputs decoding error, then output
* decryption error and stop.
*/
byte[] M = EME_PKCS1_V1_5_DECODE(EM);
/*
* 6. Output the message M.
*/
return M;
}
/**
* Method EME_PKCS1_V1_5_ENCODE
* Description: Pad encoding
*
* @param M the ciphertext message
* @param emLen the length of encr message
*
* @return encoded pad
*
* @throws IllegalBlockSizeException
*
*/
private byte[] EME_PKCS1_V1_5_ENCODE(byte[] M, int emLen)
throws IllegalBlockSizeException
{
/*
* Section 9.1.2.1 of PKCS#1v2.0
* 1. If the length of the message M is greater than emLen 10
* octets, output message too long and stop.
*/
if (M.length > emLen - 10)
{
throw new IllegalBlockSizeException("message too long");
}
/*
* 2. Generate an octet string PS of length emLen-||M||-2
* consisting of pseudorandomly generated nonzero octets.
* The length of PS will be at least 8 octets.
*/
byte[] PS =
new byte[(emLen - M.length - 2)];
// Fill the padding string with random non-zero bytes
for (int i = 0; i < PS.length; i++)
{
PS[i] = (byte) (random_.nextInt(255) + 1);
}
/*
* 3. Concatenate PS, the message M, and other padding to
* form the encoded message EM as EM = 02 || PS || 00 || M
*/
byte[] EM = new byte[emLen];
int index = 0;
EM[index++] = (byte) 0x02;
for (int i = 0; i < PS.length; i++)
{
EM[index++] = PS[i];
}
EM[index++] = (byte) 0x00;
for (int i = 0; i < M.length; i++)
{
EM[index++] = M[i];
}
/*
* 4. Output EM.
*/
return EM;
}
/**
* Method EME_PKCS1_V1_5_DECODE
* Description: Pad decoding
*
* @param EM the encrypted message
*
* @return pad
*
* @throws BadPaddingException
*
*/
private byte[] EME_PKCS1_V1_5_DECODE(byte[] EM)
throws BadPaddingException
{
/*
* Section 9.1.2.2 of PKCS#1v2.0
* 1. If the length of the encoded
* message EM is less than 10, output decoding error
* and stop.
*/
if (EM.length < 10)
{
throw new BadPaddingException("message too short");
}
/*
* 2. Separate the encoded message EM into an octet string PS
* consisting of nonzero octets and a message M as
* EM = 02 || PS || 00 || M. If the first octet of EM is not 02,
* or if there is no 00 octet to separate PS from M,
* output decoding error and stop.
*/
if (EM[0] != (byte) 0x02)
{
throw new BadPaddingException(
"message not formatted properly");
}
// Need to start by looking for the first non-zero byte
int start = 0;
while (EM[start] != (byte) 0x00)
{
start++;
if (start >= EM.length)
{
throw new BadPaddingException("bad padding");
}
}
start++; // Ignore the first 00
/*
* 3. If the length of PS is less than 8 octets,
* output decoding error and stop.
*/
if (start < 10)
{
throw new BadPaddingException("bad padding");
}
byte[] M = new byte[EM.length - start];
System.arraycopy(EM, start, M, 0, M.length);
/*
* 4. Output M.
*/
return M;
}
/**
* Method RSEAP
* Description: Performs the encryyrption
*
* @param publicKey the RSA public key
* @param m the plaintext integer
*
* @return the ciphertext integer
*
* @throws IllegalBlockSizeException
*
*/
private BigInteger RSAEP(RSAPublicKey publicKey, BigInteger m)
throws IllegalBlockSizeException
{
/*
* RSAEP ((n, e), m)
* Input: (n, e) RSA public key
* m message representative, an integer between 0 and n-1
* Output: c ciphertext representative, an integer between 0 and
* n-1; or message representative out of range
* Assumptions: public key (n, e) is valid
*/
BigInteger e = publicKey.getPublicExponent();
BigInteger n = publicKey.getModulus();
/*
* 1. If the message representative m is not between 0 and n-1,
* output message representative out of range and stop.
*/
BigInteger nMinusOne = n.subtract(BigInteger.ONE);
/*
* m > 0 and m < n-1
*/
if (m.compareTo(BigInteger.ZERO) < 0)
{
throw new IllegalBlockSizeException(
"Ciphertext too small");
}
if (m.compareTo(nMinusOne) > 0)
{
throw new IllegalBlockSizeException(
"Ciphertext too large");
}
/*
* 2. Let c = me mod n.
*/
BigInteger c = m.modPow(e, n);
/*
* 3. Output c.
*/
return c;
}
/**
* Method RSADP
* Description: Performs the decryption
*
* @param K the RSA Private Key
* @param c an integer representing
* the cipher
*
* @return the plaintext integer
*
*/
private BigInteger RSADP(RSAPrivateKey K,
BigInteger c)
{
/*
* RSADP (K, c)
* Input: K RSA private key, where K has one of the following
* forms: a pair (n, d)
* a quintuple (p, q, dP, dQ, qInv)
* c ciphertext representative, an integer between 0 and n-1
* Output: m message representative, an integer between 0 and n-1;
or
* ciphertext representative out of range
* Assumptions: private key K is valid
* Steps:
* 1. If the ciphertext representative c is not between 0 and n-1,
* output ciphertext representative out of range and stop.
*/
/*
* 2.1 Let m = cd mod n.
* PKCS #1 V2.0: RSA CRYPTOGRAPHY STANDARD 9
* Else, if the second form (p, q, dP, dQ, qInv) of K is used:
*/
if (!(K instanceof RSAPrivateCrtKey))
{
BigInteger d = K.getPrivateExponent();
BigInteger n = K.getModulus();
BigInteger m = c.modPow(d, n);
return m;
}
/*
* 2. If the first form (n, d) of K is used:
*/
RSAPrivateCrtKey privateCrtKey =
(RSAPrivateCrtKey) K;
BigInteger p = privateCrtKey.getPrimeP();
BigInteger q = privateCrtKey.getPrimeQ();
BigInteger dP =
privateCrtKey.getPrimeExponentP();
BigInteger dQ =
privateCrtKey.getPrimeExponentQ();
BigInteger qInv =
privateCrtKey.getCrtCoefficient();
/*
* 2.2 Let m1 = cdP mod p.
*/
BigInteger m1 = c.modPow(dP, p);
/*
* 2.3 Let m2 = cdQ mod q.
*/
BigInteger m2 = c.modPow(dQ, q);
/*
* 2.4 Let h = qInv ( m1 m2 ) mod p.
*/
BigInteger h = m1.subtract(m2);
h = h.multiply(qInv);
h = h.mod(p);
/*
* 2.5 Let m = m2 + h q.
*/
BigInteger m = h.multiply(q);
m = m.add(m2);
/*
* 3. Output m.
*/
return m;
}
}
Thursday, February 4, 2010
Listing
Listing 1: The RichDSA class: The DSA Signature sample application
package com.richware.chap11;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.crypto.interfaces.*;
import java.security.spec.*;
import java.math.BigInteger;
import java.io.*;
/**
* Class RichDSA
* Description: This is an example
* implementation of the DSA
* algorithm.
*
* Copyright: Copyright (c) 2002 Wiley Publishing, Inc.
* @author Rich Helton
* @version 1.0
* DISCLAIMER: Please refer to the disclaimer at the beginning of this book.
*/
public class RichDSA
{
/* the key length */
private int l_ = 1024;
/* the private key */
private BigInteger x_;
/* the public key */
private BigInteger y_;
/* the DSA parameters, see spec */
/* h is used to generate g */
private BigInteger h_;
private BigInteger p_;
private BigInteger q_;
private BigInteger g_;
/* q bit length */
int qBitLength_ = 160;
/* the SHA1 message digest */
private MessageDigest md_;
/* To debug or not to debug */
private final boolean DEBUG = false;
/* The certainty, that the generated numbers are prime. */
private final int CERTAINTY = 80;
/* The secure random generator */
private SecureRandom secureRandom_;
/* BigInteger Constants */
private static final BigInteger ZERO =
BigInteger.valueOf(0L);
private static final BigInteger ONE =
BigInteger.valueOf(1L);
private static final BigInteger TWO =
BigInteger.valueOf(2L);
/**
* Constructor RichDSA
*
*
*/
public RichDSA()
{
initKeys();
}
/**
* Method initKeys
*/
public void initKeys()
{
BigInteger x, c, qMultTwo;
try
{
md_ = MessageDigest.getInstance("SHA1");
if (secureRandom_ == null)
{
secureRandom_ = new SecureRandom();
}
int counter = 0;
boolean primesFound = false;
while (!primesFound)
{
counter = 0;
/*
* Calculate Q
*/
q_ = new BigInteger(qBitLength_, CERTAINTY,
secureRandom_);
while ((counter <>
{
/*
* q must be a divisor of p
* h ^ ((p-1) / q) mod p
* and p being prime are a
* must. X will be shifted to try
* another random and tested for prime.
* See DSA Spec.
* Appendix 2 and 3.
*/
x = reseedX();
qMultTwo = q_.multiply(TWO);
c = x.mod(qMultTwo);
/*
* Calculate P
*/
p_ = x.subtract(c.subtract(ONE));
/*
* If P is long enough and is prime,
* use it
*/
if (p_.bitLength() >= (l_))
{
if (DEBUG)
{
System.out.println("Counter :" + counter);
}
/*
* P must be prime to quit
*/
if (p_.isProbablePrime(CERTAINTY))
{
primesFound = true;
}
}
counter++;
}
}
/*
* Calculate H
*/
boolean hFound = false;
while (!hFound)
{
h_ = new BigInteger(l_, secureRandom_);
if ((h_.compareTo(ONE) > 0)
|| (h_.compareTo(p_.subtract(ONE)) <>
{
hFound = true;
}
}
/*
* Generate G, the generator
*/
BigInteger pMinusOneOverQ = p_.subtract(ONE).divide(q_);
boolean gFound = false;
while (!gFound)
{
g_ = h_.modPow(pMinusOneOverQ, p_);
if (g_.compareTo(ONE) > 0)
{
gFound = true;
}
}
/*
* Generate X, the private key
*/
x_ = new BigInteger(qBitLength_ - 1, secureRandom_);
while ((x_.compareTo(BigInteger.ZERO)) == 0)
{
x_ = new BigInteger(qBitLength_ - 1, secureRandom_);
}
/*
* Generate Y, the public key
*/
y_ = g_.modPow(x_, p_);
/*
* If DEBUG, print the results
*/
if (DEBUG)
{
System.out.println();
System.out.println("p_ :" + p_);
System.out.println();
System.out.println("q_ :" + q_);
System.out.println();
System.out.println("x_ :" + x_);
System.out.println();
System.out.println("y_ :" + y_);
System.out.println();
System.out.println("g_ :" + g_);
System.out.println();
System.out.println("h_ :" + h_);
}
}
/*
* Catches
*/
catch (Exception ex)
{
ex.printStackTrace();
}
}
/**
* Method reseedX
* Description reseed X by shifting
*
* @return a new random X
*
*/
private BigInteger reseedX()
{
byte[] shiftBytes = new byte[(l_ / 8)];
secureRandom_.nextBytes(shiftBytes);
shiftBytes[0] = (byte) (shiftBytes[0] | 128);
return (new BigInteger(1, shiftBytes));
}
/**
* Method sign
* Description: return the
* signature
* @return mostly r and s
*
*/
public byte[] sign()
{
try
{
/*
* Calculate the digest, number
*/
byte[] digest = md_.digest();
BigInteger m = new BigInteger(1, digest);
/*
* Generate k, a random number
* 0 <>
*/
BigInteger k = new BigInteger(qBitLength_ - 1,
secureRandom_);
while (k.compareTo(q_) >= 0)
{
k = new BigInteger(qBitLength_ - 1, secureRandom_);
}
/*
* Inverse of K
*/
BigInteger kInv = k.modInverse(q_);
/*
* r = (g ^ k mod p) mod q
*/
BigInteger r = (g_.modPow(k, p_)).mod(q_);
/*
* s = (k ^ -1(SHA(M) +xr)) mod q
*/
BigInteger s =
kInv.multiply((m.add(x_.multiply(r)))).mod(q_);
/*
* If DEBUG, print the results
*/
if (DEBUG)
{
System.out.println();
System.out.println("sign:r :" + r);
System.out.println();
System.out.println("sign:s :" + s);
System.out.println();
System.out.println("sign:m :" + m);
}
/*
* Put r and s in a buffer
* with some magic numbers
* to check for corruption
*/
byte[] rdata = r.toByteArray();
byte[] sdata = s.toByteArray();
byte[] data = new byte[6 + rdata.length + sdata.length];
int i = 0;
/*
* Put first magic number
*/
data[i++] = 0x40;
/*
* Put in length
*/
data[i++] = (byte) (data.length - 2);
/*
* Put in Separator
*/
data[i++] = 0x02;
/*
* Put in r length
*/
data[i++] = (byte) (rdata.length);
/*
* Put r in buffer
*/
for (int j = 0; j <>
{
data[i++] = rdata[j];
}
/*
* Put in sepaerator
*/
data[i++] = 0x02;
/*
* Put in s length
*/
data[i++] = (byte) (sdata.length);
/*
* Put s in buffer
*/
for (int j = 0; j <>
{
data[i++] = sdata[j];
}
return data;
}
/*
* Catches
*/
catch (Exception ex)
{
ex.printStackTrace();
}
return null;
}
/**
* Method update
* Description : uppdate the hash
*
* @param b the bytes
* @param offset the offset
* @param len the length
*
* @throws SignatureException
*
*/
public void update(byte[] b, int offset, int len)
throws SignatureException
{
md_.update(b, offset, len);
if (DEBUG)
{
System.out.println();
System.out.println("update:Length:" + len);
}
}
/**
* Method verify
* @param data
*
* @return
*
*/
public boolean verify(byte[] data)
{
try
{
int i = 0;
/*
* Check for the first
* magic number,
* the length
* and separator
*/
if ((data[i++] != 0x40)
|| (data[i++] != data.length - 2)
|| (data[i++] != 0x02))
{
throw new SignatureException(
"Corrupted signature data");
}
/*
* Check r length
*/
byte len = data[i++];
if (len > 21)
{
throw new SignatureException(
"Corrupted signature data");
}
/*
* Get the r buffer
*/
byte[] rdata = new byte[len];
for (int j = 0; j <>
{
rdata[j] = data[i++];
}
/*
* Check separator
*/
if (data[i++] != 0x02)
{
throw new SignatureException(
"Corrupted signature data");
}
/*
* Check s length
*/
len = data[i++];
if (len > 21)
{
throw new SignatureException(
"Corrupted signature data");
}
/*
* Get the s buffer
*/
byte[] sdata = new byte[len];
for (int j = 0; j <>
{
sdata[j] = data[i++];
}
/*
* Get r and s from Buffer
*/
BigInteger r = new BigInteger(rdata);
BigInteger s = new BigInteger(sdata);
/*
* reject the signature, if r or s >= q
*/
if ((r.compareTo(q_) >= 0) || (s.compareTo(q_) >= 0))
{
return false;
}
/*
* Get the hash value,number
*/
byte[] digest = md_.digest();
BigInteger m = new BigInteger(1, digest);
/*
* w = (S^-1) mod q
*/
BigInteger w = s.modInverse(q_);
/*
* u1 = ((SHA(M)w) mod q
*/
BigInteger u1 = m.multiply(w).mod(q_);
/*
* u2 = ((r)w) mod q
*/
BigInteger u2 = r.multiply(w).mod(q_);
if (DEBUG)
{
System.out.println();
System.out.println("verify:r :" + r);
System.out.println();
System.out.println("verify:s :" + s);
System.out.println();
System.out.println("verify:m :" + m);
System.out.println();
System.out.println("verify:w :" + w);
System.out.println();
System.out.println("verify:u1 :" + u1);
System.out.println();
System.out.println("verify:u2 :" + u2);
System.out.println();
System.out.println("verify:g :" + g_);
System.out.println();
System.out.println("verify:p :" + p_);
System.out.println();
System.out.println("verify:q :" + q_);
System.out.println();
System.out.println("verify:y :" + y_);
}
BigInteger gu1 = g_.modPow(u1, p_);
BigInteger yu2 = y_.modPow(u2, p_);
/*
* v = (((g)^ul (y) ^u2 ) mod p) mod q
*/
BigInteger v = gu1.multiply(yu2).mod(p_).mod(q_);
return v.equals(r);
}
/*
* Catches
*/
catch (Exception ex)
{
ex.printStackTrace();
}
return false;
}
/**
* Method main
* Description: This is a test driver
*
*
* @param args none
*
*/
public static void main(String[] args)
{
try
{
String localDirectory = System.getProperty("user.dir");
System.out.println("Changing directory to Chapter 11");
System.setProperty("user.dir",localDirectory +
"\\com\\richware\\chap11\\");
localDirectory = System.getProperty("user.dir");
String localFile = localDirectory + args[0];
System.out.println("Openining Chapter 11 plus the file as an
argument: " + localFile);
System.out.println("Initializing Keys... This could take several
minutes....");
/*
* Start the homegrown signer
* it automatically
* generates the keys
*/
RichDSA dsa = new RichDSA();
/*
* Start the JDK version
*/
/*
* Generate the Keypair
* get the private Key
* get the public Key
*/
KeyPairGenerator kpg =
KeyPairGenerator.getInstance("DSA");
SecureRandom r = new SecureRandom();
kpg.initialize(1024, r);
KeyPair kp = kpg.genKeyPair();
PrivateKey privKey = kp.getPrivate();
PublicKey pubKey = kp.getPublic();
/*
* Construct a sign
* and verify Signature
* If the same Signature
* class is used for both
* sign and verify in the same context
* might cause some problems
*/
Signature dsaSign =
Signature.getInstance("SHA1withDSA", "SUN");
Signature dsaVerify =
Signature.getInstance("SHA1withDSA", "SUN");
/*
* Init a sign
* with private Key
* and verify with
* a public Key
*/
dsaSign.initSign(privKey);
dsaVerify.initVerify(pubKey);
/*
* Open a File
* and read the text
*/
File inputTextFile =
new File(localFile);
FileInputStream fis =
new FileInputStream(inputTextFile);
BufferedInputStream bis =
new BufferedInputStream(fis);
byte[] buff =
new byte[(int) inputTextFile.length()];
int len;
/*
* Loop through the File
* pass the date through
* update method for
* hashing
*/
while (bis.available() != 0)
{
len = bis.read(buff);
dsa.update(buff, 0, len);
dsaSign.update(buff, 0, len);
}
/*
* Close the file
*/
bis.close();
fis.close();
/*
* Get the signatures
* the signature and public Key bytes
* are normally written to file
*/
byte[] text_signature = dsa.sign();
byte[] jdk_signature = dsaSign.sign();
/*
* Open a File
* and read the text
*/
inputTextFile = new File(localFile);
fis = new FileInputStream(inputTextFile);
bis = new BufferedInputStream(fis);
buff = new byte[(int) inputTextFile.length()];
/*
* Loop through the File
* pass the date through
* update method for
* hashing
*/
while (bis.available() != 0)
{
len = bis.read(buff);
dsa.update(buff, 0, len);
dsaVerify.update(buff, 0, len);
}
/*
* Verify with hash
* public key and
* signatures
*/
boolean verifies = dsa.verify(text_signature);
boolean jdk_verifies = dsaVerify.verify(jdk_signature);
System.out.println("RichDSA Verify : " + verifies);
System.out.println("JDK Verify : " + jdk_verifies);
/*
* Close the file
*/
bis.close();
fis.close();
}
/*
* Catches
*/
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
Saturday, October 24, 2009
Old wine in a new bottle: The Story of Remixes
This seems to be ubiquitous buzzword in our music industry today. With music companies releasing scores of remixed albums, the songs from past have again made way to our TV screens but in a new ‘avtaar’.
if u wanna read about this article click on the link below :
STRUGGLE FOR EXISTANCE
why should i live..........
why should i live
in this lost world?
king of darkness
is roaring here!
if u wanna read about this article click on the link below :
Bigg Boss Fever
Big Boss Season 3 is a reality show in which few celebrities, in terms of Big Boss called as house mates, stay together for set period of days. In this season that is season 3, number days these people would be living for about 84 days. These people are made to stay completely in isolation from the outside world in a well equipped house, with a garden.
if u wanna read about this article click on the link below :
Cricket owes its current charm to technology
These days so much of cricket is being played, that people have lost interest in the game. Many a times it happens that once we switch on the televison set we see a cricket match going on. With the amount of replays of matches being shown, one does not know if one is seeing a live match or a recorded one. Only after watching the match continuously for about 10 minutes, one gets to know whether the match being telecast is a live match or a recorded one. Too much cricket is one of the reasons why the game has lost its charm.
if u wanna read about this article click on the link below :
Subscribe to:
Posts (Atom)
!...WeLcOmE tO mY wOrLd..!
Search This Blog
Followers
Blog Archive
About Me
- Lohit Seth
- Hello Friends Lohit here. if u wanna know me then go to my orkut page and add me http://www.orkut.co.in/Main#Profile?rl=ls&uid=15846901972849568761