001 /* 002 * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org 003 * Copyright (C) 2011 NightLabs Consulting GmbH 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 package org.cumulus4j.crypto.internal.symmetric; 019 020 import org.bouncycastle.crypto.BlockCipher; 021 import org.bouncycastle.crypto.BufferedBlockCipher; 022 import org.bouncycastle.crypto.CipherParameters; 023 import org.bouncycastle.crypto.CryptoException; 024 import org.bouncycastle.crypto.DataLengthException; 025 import org.bouncycastle.crypto.modes.CBCBlockCipher; 026 import org.bouncycastle.crypto.modes.CFBBlockCipher; 027 import org.bouncycastle.crypto.modes.CTSBlockCipher; 028 import org.bouncycastle.crypto.modes.OFBBlockCipher; 029 import org.cumulus4j.crypto.AbstractCipher; 030 import org.cumulus4j.crypto.CipherOperationMode; 031 import org.cumulus4j.crypto.CryptoRegistry; 032 033 /** 034 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de 035 */ 036 public class BufferedBlockCipherImpl 037 extends AbstractCipher 038 { 039 private BufferedBlockCipher delegate; 040 041 public BufferedBlockCipherImpl(String transformation, BufferedBlockCipher delegate) { 042 super(transformation); 043 this.delegate = delegate; 044 } 045 046 @Override 047 public void _init(CipherOperationMode mode, CipherParameters parameters) 048 throws IllegalArgumentException 049 { 050 delegate.init(CipherOperationMode.ENCRYPT == mode, parameters); 051 } 052 053 @Override 054 public int getInputBlockSize() { 055 return delegate.getBlockSize(); 056 // return delegate.getUnderlyingCipher().getBlockSize(); 057 } 058 059 @Override 060 public int getOutputBlockSize() { 061 return delegate.getBlockSize(); 062 // return delegate.getUnderlyingCipher().getBlockSize(); 063 } 064 065 @Override 066 public void reset() { 067 delegate.reset(); 068 } 069 070 @Override 071 public int getUpdateOutputSize(int len) { 072 return delegate.getUpdateOutputSize(len); 073 } 074 075 @Override 076 public int getOutputSize(int length) { 077 return delegate.getOutputSize(length); 078 } 079 080 @Override 081 public int update(byte in, byte[] out, int outOff) 082 throws DataLengthException, IllegalStateException, CryptoException 083 { 084 return delegate.processByte(in, out, outOff); 085 } 086 087 @Override 088 public int update(byte[] in, int inOff, int len, byte[] out, int outOff) 089 throws DataLengthException, IllegalStateException, CryptoException 090 { 091 return delegate.processBytes(in, inOff, len, out, outOff); 092 } 093 094 @Override 095 public int doFinal(byte[] out, int outOff) 096 throws DataLengthException, IllegalStateException, CryptoException 097 { 098 return delegate.doFinal(out, outOff); 099 } 100 101 private int ivSize = -1; 102 103 @Override 104 public int getIVSize() 105 { 106 if (ivSize < 0) { 107 String mode = CryptoRegistry.splitTransformation(getTransformation())[1]; 108 if ("".equals(mode) || "ECB".equals(mode)) 109 ivSize = 0; // No block cipher mode (i.e. ECB) => no IV. 110 else { 111 if (delegate instanceof CTSBlockCipher) { 112 CTSBlockCipher cts = (CTSBlockCipher) delegate; 113 if (cts.getUnderlyingCipher() instanceof CBCBlockCipher) 114 ivSize = cts.getUnderlyingCipher().getBlockSize(); 115 else 116 ivSize = 0; 117 } 118 else { 119 BlockCipher underlyingCipher = delegate.getUnderlyingCipher(); 120 121 if (underlyingCipher instanceof CFBBlockCipher) 122 ivSize = ((CFBBlockCipher)underlyingCipher).getUnderlyingCipher().getBlockSize(); 123 else if (underlyingCipher instanceof OFBBlockCipher) 124 ivSize = ((OFBBlockCipher)underlyingCipher).getUnderlyingCipher().getBlockSize(); 125 else 126 ivSize = underlyingCipher.getBlockSize(); 127 } 128 } 129 } 130 return ivSize; 131 } 132 133 // @Override 134 // public AsymmetricCipherKeyPairGenerator createKeyPairGenerator(boolean initWithDefaults) 135 // throws UnsupportedOperationException 136 // { 137 // throw new UnsupportedOperationException("This is a SYMMETRIC cipher! Cannot get an appropriate key pair generator!"); 138 // } 139 // 140 // @Override 141 // public SecretKeyGenerator createSecretKeyGenerator(boolean initWithDefaults) 142 // { 143 // String algorithmName = CryptoRegistry.splitTransformation(getTransformation())[0]; 144 // try { 145 // return CryptoRegistry.sharedInstance().createSecretKeyGenerator(algorithmName, initWithDefaults); 146 // } catch (NoSuchAlgorithmException e) { 147 // throw new RuntimeException(e); // We should be able to provide an SecretKeyGenerator for every Cipher => RuntimeException 148 // } 149 // } 150 }