1 16 17 package de.schlichtherle.crypto.io.raes; 18 19 import de.schlichtherle.crypto.generators.DigestRandom; 20 import de.schlichtherle.crypto.modes.SICSeekableBlockCipher; 21 import de.schlichtherle.io.util.LEDataOutputStream; 22 23 import java.io.IOException ; 24 import java.io.OutputStream ; 25 26 import org.bouncycastle.crypto.BufferedBlockCipher; 27 import org.bouncycastle.crypto.CipherParameters; 28 import org.bouncycastle.crypto.Digest; 29 import org.bouncycastle.crypto.Mac; 30 import org.bouncycastle.crypto.PBEParametersGenerator; 31 import org.bouncycastle.crypto.digests.SHA256Digest; 32 import org.bouncycastle.crypto.engines.AESFastEngine; 33 import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator; 34 import org.bouncycastle.crypto.io.MacOutputStream; 35 import org.bouncycastle.crypto.macs.HMac; 36 import org.bouncycastle.crypto.params.KeyParameter; 37 import org.bouncycastle.crypto.params.ParametersWithIV; 38 39 46 class Type0RaesOutputStream extends RaesOutputStream { 47 48 51 final static int ITERATION_COUNT = 2005; 53 54 private int keyStrengthBits; 55 56 57 private Mac mac; 58 59 60 private Mac klac; 61 62 66 private LEDataOutputStream dos; 67 68 69 private long start; 70 71 72 private boolean closed; 73 74 Type0RaesOutputStream( 75 final OutputStream out, 76 final Type0RaesParameters parameters) 77 throws NullPointerException , 78 IllegalArgumentException , 79 RaesKeyException, 80 IOException { 81 super(out, null); 82 83 assert out != null; 84 assert parameters != null; 85 86 final char[] passwd = parameters.getCreatePasswd(); 88 if (passwd == null) 89 throw new RaesKeyException(); 90 final int keyStrength = parameters.getKeyStrength(); 91 if (keyStrength != Type0RaesParameters.KEY_STRENGTH_128 92 && keyStrength != Type0RaesParameters.KEY_STRENGTH_192 93 && keyStrength != Type0RaesParameters.KEY_STRENGTH_256) 94 throw new IllegalArgumentException ( 95 "Illegal cipher key strength: " 96 + keyStrength 97 + "!"); 98 99 final Digest digest = new SHA256Digest(); 101 102 final int keyStrengthBytes = 16 + keyStrength * 8; 104 keyStrengthBits = keyStrengthBytes * 8; assert digest.getDigestSize() >= keyStrengthBytes; 106 final byte[] salt = new byte[keyStrengthBytes]; 107 new DigestRandom(digest).nextBytes(salt); 108 109 final PBEParametersGenerator paramGen 111 = new PKCS12ParametersGenerator(digest); 112 final byte[] pass = PBEParametersGenerator.PKCS12PasswordToBytes(passwd); 113 for (int i = passwd.length; --i >= 0; ) passwd[i] = 0; 115 116 paramGen.init(pass, salt, ITERATION_COUNT); 117 final ParametersWithIV cipherParam 120 = (ParametersWithIV) paramGen.generateDerivedParameters( 121 keyStrengthBits, AES_BLOCK_SIZE); 122 final CipherParameters macParam 123 = paramGen.generateDerivedMacParameters(keyStrengthBits); 124 for (int i = pass.length; --i >= 0; ) pass[i] = 0; 126 127 final BufferedBlockCipher cipher = new BufferedBlockCipher( 129 new SICSeekableBlockCipher( 130 new AESFastEngine())); 131 cipher.init(true, cipherParam); 132 133 mac = new HMac(new SHA256Digest()); 135 mac.init(macParam); 136 137 klac = new HMac(digest); 139 klac.init(macParam); 140 final byte[] cipherKey 141 = ((KeyParameter) cipherParam.getParameters()).getKey(); 142 klac.update(cipherKey, 0, cipherKey.length); 143 144 dos = new LEDataOutputStream(out); 146 this.out = new MacOutputStream(dos, mac); 147 148 dos.writeInt(RAES_SIGNATURE); 150 dos.writeByte(ENVELOPE_TYPE_0); 151 dos.writeByte(keyStrength); 152 dos.writeShort(ITERATION_COUNT); 153 dos.write(salt); 154 155 start = dos.size(); 157 assert start == ENVELOPE_TYPE_0_HEADER_LEN_WO_SALT + salt.length; 158 159 this.cipher = cipher; 161 } 162 163 public int getKeySizeBits() { 164 return keyStrengthBits; 165 } 166 167 public void close() throws IOException { 168 if (!closed) { 170 closed = true; 171 try { 172 finish(); 174 175 final long trailer = dos.size(); 176 177 assert mac.getMacSize() == klac.getMacSize(); 178 final byte[] buf = new byte[mac.getMacSize()]; int bufLen; 180 181 final long length = trailer - start; klac(klac, length, buf); 186 dos.write(buf, 0, buf.length / 2); 187 188 bufLen = mac.doFinal(buf, 0); 192 assert bufLen == buf.length; 193 dos.write(buf, 0, buf.length / 2); 194 195 assert dos.size() - trailer == buf.length; 196 } finally { 197 super.close(); 198 } 199 } 200 } 201 } 202 | Popular Tags |