1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.bouncycastle.crypto.encodings; 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.SecureRandom; 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.AsymmetricBlockCipher; 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.CipherParameters; 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.Digest; 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.InvalidCipherTextException; 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.digests.SHA1Digest; 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.AsymmetricKeyParameter; 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.ParametersWithRandom; 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Optimal Asymmetric Encryption Padding (OAEP) - see PKCS 1 V 2. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class OAEPEncoding 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project implements AsymmetricBlockCipher 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private byte[] defHash; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private Digest hash; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private AsymmetricBlockCipher engine; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private SecureRandom random; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private boolean forEncryption; 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public OAEPEncoding( 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project AsymmetricBlockCipher cipher) 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this(cipher, new SHA1Digest(), null); 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public OAEPEncoding( 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project AsymmetricBlockCipher cipher, 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Digest hash) 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this(cipher, hash, null); 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public OAEPEncoding( 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project AsymmetricBlockCipher cipher, 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Digest hash, 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] encodingParams) 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.engine = cipher; 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.hash = hash; 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.defHash = new byte[hash.getDigestSize()]; 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (encodingParams != null) 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash.update(encodingParams, 0, encodingParams.length); 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash.doFinal(defHash, 0); 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public AsymmetricBlockCipher getUnderlyingCipher() 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return engine; 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void init( 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean forEncryption, 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CipherParameters param) 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project AsymmetricKeyParameter kParam; 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (param instanceof ParametersWithRandom) 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ParametersWithRandom rParam = (ParametersWithRandom)param; 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.random = rParam.getRandom(); 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kParam = (AsymmetricKeyParameter)rParam.getParameters(); 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.random = new SecureRandom(); 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kParam = (AsymmetricKeyParameter)param; 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project engine.init(forEncryption, kParam); 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.forEncryption = forEncryption; 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getInputBlockSize() 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int baseBlockSize = engine.getInputBlockSize(); 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (forEncryption) 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return baseBlockSize - 1 - 2 * defHash.length; 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return baseBlockSize; 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getOutputBlockSize() 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int baseBlockSize = engine.getOutputBlockSize(); 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (forEncryption) 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return baseBlockSize; 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return baseBlockSize - 1 - 2 * defHash.length; 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public byte[] processBlock( 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] in, 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int inOff, 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int inLen) 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throws InvalidCipherTextException 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (forEncryption) 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return encodeBlock(in, inOff, inLen); 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return decodeBlock(in, inOff, inLen); 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public byte[] encodeBlock( 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] in, 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int inOff, 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int inLen) 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throws InvalidCipherTextException 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] block = new byte[getInputBlockSize() + 1 + 2 * defHash.length]; 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // copy in the message 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(in, inOff, block, block.length - inLen, inLen); 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // add sentinel 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project block[block.length - inLen - 1] = 0x01; 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // as the block is already zeroed - there's no need to add PS (the >= 0 pad of 0) 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // add the hash of the encoding params. 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(defHash, 0, block, defHash.length, defHash.length); 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // generate the seed. 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] seed = new byte[defHash.length]; 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project random.nextBytes(seed); 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // mask the message block. 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] mask = maskGeneratorFunction1(seed, 0, seed.length, block.length - defHash.length); 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = defHash.length; i != block.length; i++) 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project block[i] ^= mask[i - defHash.length]; 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // add in the seed 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(seed, 0, block, 0, defHash.length); 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // mask the seed. 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mask = maskGeneratorFunction1( 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project block, defHash.length, block.length - defHash.length, defHash.length); 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i != defHash.length; i++) 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project block[i] ^= mask[i]; 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return engine.processBlock(block, 0, block.length); 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @exception InvalidCipherTextException if the decrypted block turns out to 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be badly formatted. 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public byte[] decodeBlock( 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] in, 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int inOff, 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int inLen) 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throws InvalidCipherTextException 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] data = engine.processBlock(in, inOff, inLen); 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] block = null; 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // as we may have zeros in our leading bytes for the block we produced 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // on encryption, we need to make sure our decrypted block comes back 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // the same size. 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (data.length < engine.getOutputBlockSize()) 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project block = new byte[engine.getOutputBlockSize()]; 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(data, 0, block, block.length - data.length, data.length); 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project block = data; 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (block.length < (2 * defHash.length) + 1) 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new InvalidCipherTextException("data too short"); 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // unmask the seed. 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] mask = maskGeneratorFunction1( 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project block, defHash.length, block.length - defHash.length, defHash.length); 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i != defHash.length; i++) 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project block[i] ^= mask[i]; 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // unmask the message block. 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mask = maskGeneratorFunction1(block, 0, defHash.length, block.length - defHash.length); 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = defHash.length; i != block.length; i++) 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project block[i] ^= mask[i - defHash.length]; 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // check the hash of the encoding params. 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i != defHash.length; i++) 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (defHash[i] != block[defHash.length + i]) 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new InvalidCipherTextException("data hash wrong"); 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // find the data block 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int start; 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (start = 2 * defHash.length; start != block.length; start++) 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (block[start] == 1 || block[start] != 0) 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (start >= (block.length - 1) || block[start] != 1) 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new InvalidCipherTextException("data start wrong " + start); 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start++; 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // extract the data block 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] output = new byte[block.length - start]; 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(block, start, output, 0, output.length); 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return output; 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * int to octet string. 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void ItoOSP( 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i, 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] sp) 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sp[0] = (byte)(i >>> 24); 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sp[1] = (byte)(i >>> 16); 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sp[2] = (byte)(i >>> 8); 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sp[3] = (byte)(i >>> 0); 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * mask generator function, as described in PKCS1v2. 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private byte[] maskGeneratorFunction1( 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] Z, 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int zOff, 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int zLen, 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int length) 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] mask = new byte[length]; 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] hashBuf = new byte[defHash.length]; 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] C = new byte[4]; 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int counter = 0; 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash.reset(); 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project do 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ItoOSP(counter, C); 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash.update(Z, zOff, zLen); 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash.update(C, 0, C.length); 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash.doFinal(hashBuf, 0); 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(hashBuf, 0, mask, counter * defHash.length, defHash.length); 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (++counter < (length / defHash.length)); 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((counter * defHash.length) < length) 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ItoOSP(counter, C); 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash.update(Z, zOff, zLen); 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash.update(C, 0, C.length); 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash.doFinal(hashBuf, 0); 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(hashBuf, 0, mask, counter * defHash.length, mask.length - (counter * defHash.length)); 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return mask; 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 343