/* * Copyright 2011 David Brazdil * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package uk.ac.cam.db538.cryptosms.crypto; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import org.spongycastle.crypto.digests.SHA256Digest; import org.spongycastle.crypto.macs.HMac; import org.spongycastle.crypto.params.KeyParameter; import uk.ac.cam.db538.cryptosms.utils.LowLevel; /* * Class implementing the EncryptionInterface but not encrypting anything at all */ public class EncryptionNone implements EncryptionInterface { /** * Inits the encryption. */ public static void initEncryption() { Encryption.setEncryption(new EncryptionNone()); } private SecureRandom mRandom = null; /** * Instantiates a new encryption none. */ public EncryptionNone() { try { mRandom = SecureRandom.getInstance("SHA1PRNG"); } catch (NoSuchAlgorithmException e){ throw new RuntimeException("No secure random available!"); } } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#decryptSymmetric(byte[], byte[], int) */ @Override public byte[] decryptSymmetric(byte[] data, byte[] key, int blocks) throws EncryptionException { int length = blocks * Encryption.SYM_BLOCK_LENGTH; byte[] dataDecrypted = LowLevel.cutData(data, Encryption.SYM_OVERHEAD, length - Encryption.SYM_OVERHEAD); byte[] hashSaved = LowLevel.cutData(data, 0, Encryption.HMAC_LENGTH); byte[] hashReal = getHMAC(dataDecrypted, key); for (int i = 0; i < Encryption.HMAC_LENGTH; ++i) if (hashSaved[i] != hashReal[i]) throw new EncryptionException(new Exception(LowLevel.toHex(dataDecrypted))); return dataDecrypted; } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#decryptSymmetric(byte[], byte[]) */ @Override public byte[] decryptSymmetric(byte[] data, byte[] key) throws EncryptionException { return decryptSymmetric(data, key, data.length / Encryption.SYM_BLOCK_LENGTH); } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#decryptSymmetricWithMasterKey(byte[]) */ @Override public byte[] decryptSymmetricWithMasterKey(byte[] data) throws EncryptionException { return decryptSymmetricWithMasterKey(data, false); } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#encryptSymmetric(byte[], byte[]) */ @Override public byte[] encryptSymmetric(byte[] data, byte[] key) { int alignedLength = Encryption.getEncryption().getSymmetricAlignedLength(data.length); byte[] buffer = new byte[alignedLength + Encryption.HMAC_LENGTH + Encryption.SYM_IV_LENGTH]; data = LowLevel.wrapData(data, alignedLength); System.arraycopy(getHMAC(data, key), 0, buffer, 0, Encryption.HMAC_LENGTH); for (int i = 0; i < Encryption.SYM_IV_LENGTH; ++i) buffer[Encryption.HMAC_LENGTH + i] = (byte) 0x49; System.arraycopy(data, 0, buffer, Encryption.SYM_OVERHEAD, alignedLength); return buffer; } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#encryptSymmetricWithMasterKey(byte[]) */ @Override public byte[] encryptSymmetricWithMasterKey(byte[] data) throws EncryptionException { return encryptSymmetricWithMasterKey(data, false); } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#generateRandomData(int) */ @Override public byte[] generateRandomData(int length) { byte[] data = new byte[length]; mRandom.nextBytes(data); return data; } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#getSymmetricAlignedLength(int) */ @Override public int getSymmetricAlignedLength(int length) { return LowLevel.closestGreatestMultiple(length, Encryption.SYM_BLOCK_LENGTH); } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#getSymmetricEncryptedLength(int) */ @Override public int getSymmetricEncryptedLength(int length) { return getSymmetricAlignedLength(length) + Encryption.SYM_OVERHEAD; } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#getHash(byte[]) */ @Override public byte[] getHash(byte[] data) { SHA256Digest sha256 = new SHA256Digest(); byte[] result = new byte[Encryption.HASH_LENGTH]; sha256.update(data, 0, data.length); if (sha256.doFinal(result, 0) == Encryption.HASH_LENGTH) return result; else throw new RuntimeException("SHA-256 internal error"); } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#getHMAC(byte[], byte[]) */ @Override public byte[] getHMAC(byte[] data, byte[] key) { HMac mac = new HMac(new SHA256Digest()); mac.init(new KeyParameter(key)); byte[] result = new byte[Encryption.HMAC_LENGTH]; mac.update(data, 0, data.length); if (mac.doFinal(result, 0) == Encryption.HMAC_LENGTH) return result; else throw new RuntimeException("HMAC internal error"); } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#encryptSymmetricWithMasterKey(byte[], boolean) */ @Override public byte[] encryptSymmetricWithMasterKey(byte[] data, boolean forceLogIn) throws EncryptionException { return encryptSymmetric(data, null); } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#decryptSymmetricWithMasterKey(byte[], boolean) */ @Override public byte[] decryptSymmetricWithMasterKey(byte[] data, boolean forceLogIn) throws EncryptionException { return decryptSymmetric(data, null); } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#sign(byte[]) */ @Override public byte[] sign(byte[] dataEncrypted) throws EncryptionException { return null; } /* (non-Javadoc) * @see uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface#verify(byte[], byte[], long) */ @Override public boolean verify(byte[] data, byte[] signature, long contactId) throws EncryptionException { return false; } @Override public SecureRandom getRandom() { return mRandom; } }