📄 richrsacipher.java
字号:
/*
* 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 decryyrption
*
* @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))//RSAPrivateCrtKey是继承RSAPrivateKey的一个类.
/* jdk1.5的API中是如此说明的:
The interface to an RSA private key, as defined in the PKCS#1 standard, using the Chinese Remainder Theorem (CRT) information values.
*/
{
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;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -