private byte[] DecodeBlockOrRandom(byte[] input, int inOff, int inLen) { if (!this.forPrivateKey) { throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing"); } byte[] array = this.engine.ProcessBlock(input, inOff, inLen); byte[] array2; if (this.fallback == null) { array2 = new byte[this.pLen]; this.random.NextBytes(array2); } else { array2 = this.fallback; } if (array.Length < this.GetOutputBlockSize()) { throw new InvalidCipherTextException("block truncated"); } if (this.useStrictLength && array.Length != this.engine.GetOutputBlockSize()) { throw new InvalidCipherTextException("block incorrect size"); } int num = Pkcs1Encoding.CheckPkcs1Encoding(array, this.pLen); byte[] array3 = new byte[this.pLen]; for (int i = 0; i < this.pLen; i++) { array3[i] = (byte)(((int)array[i + (array.Length - this.pLen)] & ~num) | ((int)array2[i] & num)); } return(array3); }
/** * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct. * * @param in The encrypted block. * @param inOff Offset in the encrypted block. * @param inLen Length of the encrypted block. * @param pLen Length of the desired output. * @return The plaintext without padding, or a random value if the padding was incorrect. * * @throws InvalidCipherTextException */ private byte[] DecodeBlockOrRandom(byte[] input, int inOff, int inLen) { if (!forPrivateKey) { throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing"); } byte[] block = engine.ProcessBlock(input, inOff, inLen); byte[] random = null; if (this.fallback == null) { random = new byte[this.pLen]; this.random.NextBytes(random); } else { random = fallback; } /* * TODO: This is a potential dangerous side channel. However, you can * fix this by changing the RSA engine in a way, that it will always * return blocks of the same length and prepend them with 0 bytes if * needed. */ if (block.Length < GetOutputBlockSize()) { throw new InvalidCipherTextException("block truncated"); } /* * TODO: Potential side channel. Fix it by making the engine always * return blocks of the correct length. */ if (useStrictLength && block.Length != engine.GetOutputBlockSize()) { throw new InvalidCipherTextException("block incorrect size"); } /* * Check the padding. */ int correct = Pkcs1Encoding.CheckPkcs1Encoding(block, this.pLen); /* * Now, to a constant time constant memory copy of the decrypted value * or the random value, depending on the validity of the padding. */ byte[] result = new byte[this.pLen]; for (int i = 0; i < this.pLen; i++) { result[i] = (byte)((block[i + (block.Length - pLen)] & (~correct)) | (random[i] & correct)); } return(result); }