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.CipherParameters;
021    import org.bouncycastle.crypto.CryptoException;
022    import org.bouncycastle.crypto.DataLengthException;
023    import org.bouncycastle.crypto.StreamCipher;
024    import org.bouncycastle.crypto.engines.Grain128Engine;
025    import org.bouncycastle.crypto.engines.Grainv1Engine;
026    import org.bouncycastle.crypto.engines.HC128Engine;
027    import org.bouncycastle.crypto.engines.HC256Engine;
028    import org.bouncycastle.crypto.engines.ISAACEngine;
029    import org.bouncycastle.crypto.engines.RC4Engine;
030    import org.bouncycastle.crypto.engines.Salsa20Engine;
031    import org.cumulus4j.crypto.AbstractCipher;
032    import org.cumulus4j.crypto.CipherOperationMode;
033    
034    /**
035     * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
036     */
037    public class StreamCipherImpl
038    extends AbstractCipher
039    {
040            private StreamCipher delegate;
041    
042            public StreamCipherImpl(String transformation, StreamCipher delegate) {
043                    super(transformation);
044                    this.delegate = delegate;
045            }
046    
047            @Override
048            public void _init(CipherOperationMode mode, CipherParameters parameters)
049            throws IllegalArgumentException
050            {
051                    delegate.init(CipherOperationMode.ENCRYPT == mode, parameters);
052            }
053    
054            @Override
055            public void reset() {
056                    delegate.reset();
057            }
058    
059            @Override
060            public int getInputBlockSize() {
061                    return 1;
062            }
063    
064            @Override
065            public int getOutputBlockSize() {
066                    return 1;
067            }
068    
069            @Override
070            public int getUpdateOutputSize(int length) {
071                    return length;
072            }
073    
074            @Override
075            public int getOutputSize(int length) {
076                    return length;
077            }
078    
079            @Override
080            public int update(byte in, byte[] out, int outOff)
081            throws DataLengthException, IllegalStateException, CryptoException
082            {
083                    out[outOff] = delegate.returnByte(in);
084                    return 1;
085            }
086    
087            @Override
088            public int update(byte[] in, int inOff, int inLen, byte[] out, int outOff)
089            throws DataLengthException, IllegalStateException, CryptoException
090            {
091                    delegate.processBytes(in, inOff, inLen, out, outOff);
092                    return inLen;
093            }
094    
095            @Override
096            public int doFinal(byte[] out, int outOff)
097            throws DataLengthException, IllegalStateException, CryptoException
098            {
099                    return 0;
100            }
101    
102            private int ivSize = -1;
103    
104            @Override
105            public int getIVSize()
106            {
107                    if (ivSize < 0) {
108                            if (delegate instanceof Grainv1Engine)
109                                    ivSize = 8;
110                            else if (delegate instanceof Grain128Engine)
111                                    ivSize = 12;
112                            else if (delegate instanceof HC128Engine)
113                                    ivSize = 16;
114                            else if (delegate instanceof HC256Engine)
115                                    ivSize = 32;
116                            else if (delegate instanceof ISAACEngine)
117                                    ivSize = 0;
118                            else if (delegate instanceof RC4Engine)
119                                    ivSize = 0;
120                            else if (delegate instanceof Salsa20Engine)
121                                    ivSize = 8;
122                            else
123                                    throw new UnsupportedOperationException("For this delegate cipher type, this operation is not yet supported!");
124                    }
125                    return ivSize;
126            }
127    
128    //      @Override
129    //      public AsymmetricCipherKeyPairGenerator createKeyPairGenerator(boolean initWithDefaults)
130    //      throws UnsupportedOperationException
131    //      {
132    //              throw new UnsupportedOperationException("This is a SYMMETRIC cipher! Cannot get an appropriate key pair generator!");
133    //      }
134    //
135    //      @Override
136    //      public SecretKeyGenerator createSecretKeyGenerator(boolean initWithDefaults)
137    //      {
138    //              String algorithmName = CryptoRegistry.splitTransformation(getTransformation())[0];
139    //              try {
140    //                      return CryptoRegistry.sharedInstance().createSecretKeyGenerator(algorithmName, initWithDefaults);
141    //              } catch (NoSuchAlgorithmException e) {
142    //                      throw new RuntimeException(e); // We should be able to provide an SecretKeyGenerator for every Cipher => RuntimeException
143    //              }
144    //      }
145    }