PSSSignerpublic class PSSSigner extends Object implements org.bouncycastle.crypto.SignerRSA-PSS as described in PKCS# 1 v 2.1.
Note: the usual value for the salt length is the number of
bytes in the hash function. |
Fields Summary |
---|
public static final byte | TRAILER_IMPLICIT | private org.bouncycastle.crypto.Digest | digest | private org.bouncycastle.crypto.AsymmetricBlockCipher | cipher | private SecureRandom | random | private int | hLen | private int | sLen | private int | emBits | private byte[] | salt | private byte[] | mDash | private byte[] | block | private byte | trailer |
Methods Summary |
---|
private void | ItoOSP(int i, byte[] sp)int to octet string.
sp[0] = (byte)(i >>> 24);
sp[1] = (byte)(i >>> 16);
sp[2] = (byte)(i >>> 8);
sp[3] = (byte)(i >>> 0);
| private void | clearBlock(byte[] block)clear possible sensitive data
for (int i = 0; i != block.length; i++)
{
block[i] = 0;
}
| public byte[] | generateSignature()generate a signature for the message we've been loaded with using
the key we were initialised with.
if (emBits < (8 * hLen + 8 * sLen + 9))
{
throw new DataLengthException("encoding error");
}
digest.doFinal(mDash, mDash.length - hLen - sLen);
if (sLen != 0)
{
random.nextBytes(salt);
System.arraycopy(salt, 0, mDash, mDash.length - sLen, sLen);
}
byte[] h = new byte[hLen];
digest.update(mDash, 0, mDash.length);
digest.doFinal(h, 0);
block[block.length - sLen - 1 - hLen - 1] = 0x01;
System.arraycopy(salt, 0, block, block.length - sLen - hLen - 1, sLen);
byte[] dbMask = maskGeneratorFunction1(h, 0, h.length, block.length - hLen - 1);
for (int i = 0; i != dbMask.length; i++)
{
block[i] ^= dbMask[i];
}
block[0] &= (0xff >> ((block.length * 8) - emBits));
System.arraycopy(h, 0, block, block.length - hLen - 1, hLen);
block[block.length - 1] = trailer;
byte[] b = cipher.processBlock(block, 0, block.length);
clearBlock(block);
return b;
| public void | init(boolean forSigning, org.bouncycastle.crypto.CipherParameters param)
RSAKeyParameters kParam = null;
if (param instanceof ParametersWithRandom)
{
ParametersWithRandom p = (ParametersWithRandom)param;
kParam = (RSAKeyParameters)p.getParameters();
random = p.getRandom();
}
else
{
kParam = (RSAKeyParameters)param;
if (forSigning)
{
random = new SecureRandom();
}
}
cipher.init(forSigning, kParam);
emBits = kParam.getModulus().bitLength() - 1;
block = new byte[(emBits + 7) / 8];
reset();
| private byte[] | maskGeneratorFunction1(byte[] Z, int zOff, int zLen, int length)mask generator function, as described in PKCS1v2.
byte[] mask = new byte[length];
byte[] hashBuf = new byte[hLen];
byte[] C = new byte[4];
int counter = 0;
digest.reset();
while (counter < (length / hLen))
{
ItoOSP(counter, C);
digest.update(Z, zOff, zLen);
digest.update(C, 0, C.length);
digest.doFinal(hashBuf, 0);
System.arraycopy(hashBuf, 0, mask, counter * hLen, hLen);
counter++;
}
if ((counter * hLen) < length)
{
ItoOSP(counter, C);
digest.update(Z, zOff, zLen);
digest.update(C, 0, C.length);
digest.doFinal(hashBuf, 0);
System.arraycopy(hashBuf, 0, mask, counter * hLen, mask.length - (counter * hLen));
}
return mask;
| public void | reset()reset the internal state
digest.reset();
| public void | update(byte b)update the internal digest with the byte b
digest.update(b);
| public void | update(byte[] in, int off, int len)update the internal digest with the byte array in
digest.update(in, off, len);
| public boolean | verifySignature(byte[] signature)return true if the internal state represents the signature described
in the passed in array.
if (emBits < (8 * hLen + 8 * sLen + 9))
{
return false;
}
digest.doFinal(mDash, mDash.length - hLen - sLen);
try
{
byte[] b = cipher.processBlock(signature, 0, signature.length);
System.arraycopy(b, 0, block, block.length - b.length, b.length);
}
catch (Exception e)
{
return false;
}
if (block[block.length - 1] != trailer)
{
clearBlock(block);
return false;
}
byte[] dbMask = maskGeneratorFunction1(block, block.length - hLen - 1, hLen, block.length - hLen - 1);
for (int i = 0; i != dbMask.length; i++)
{
block[i] ^= dbMask[i];
}
block[0] &= (0xff >> ((block.length * 8) - emBits));
for (int i = 0; i != block.length - hLen - sLen - 2; i++)
{
if (block[i] != 0)
{
clearBlock(block);
return false;
}
}
if (block[block.length - hLen - sLen - 2] != 0x01)
{
clearBlock(block);
return false;
}
System.arraycopy(block, block.length - sLen - hLen - 1, mDash, mDash.length - sLen, sLen);
digest.update(mDash, 0, mDash.length);
digest.doFinal(mDash, mDash.length - hLen);
for (int i = block.length - hLen - 1, j = mDash.length - hLen;
j != mDash.length; i++, j++)
{
if ((block[i] ^ mDash[j]) != 0)
{
clearBlock(mDash);
clearBlock(block);
return false;
}
}
clearBlock(mDash);
clearBlock(block);
return true;
|
|