Java tutorial
/* @(#)Crypter_Blowfish.java - zac@zacwolf.com * * Utility class for specifying an BlowFish specific Crypter * Licensed under the MIT License (MIT) Copyright (c) 2014 Zac Morris Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package com.zacwolf.commons.crypto; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.spec.InvalidKeySpecException; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; public final class Crypter_Blowfish extends Crypter { private static final long serialVersionUID = -916069317778253291L; private static final String mytype = "Blowfish"; private static final String mycipher = "Blowfish/CBC/PKCS5Padding"; private static final int mykeysizemax = 256; private final byte[] key; private final SecretKeySpec secretkey; /** * @param keyStore * @param keystorepass * @param alias * @throws UnrecoverableKeyException * @throws NoSuchAlgorithmException * @throws KeyStoreException */ public Crypter_Blowfish(final KeyStore keyStore, final String keystorepass, final String alias) throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException { this(keyStore.getKey(alias, keystorepass.toCharArray()).getEncoded()); } /** * @param keyStore * @param keystorepass * @param alias * @param cipher * @throws UnrecoverableKeyException * @throws NoSuchAlgorithmException * @throws KeyStoreException */ public Crypter_Blowfish(final KeyStore keyStore, final String keystorepass, final String alias, final String cipher) throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException { this(keyStore.getKey(alias, keystorepass.toCharArray()).getEncoded(), cipher); } /** * @param keyStore * @param keystorepass * @param alias * @param cipher * @param salter * @throws UnrecoverableKeyException * @throws NoSuchAlgorithmException * @throws KeyStoreException */ public Crypter_Blowfish(final KeyStore keyStore, final String keystorepass, final String alias, final String cipher, final SecureRandom salter) throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException { this(keyStore.getKey(alias, keystorepass.toCharArray()).getEncoded(), cipher, salter); } /** * @param keyStore * @param keystorepass * @param alias * @throws UnrecoverableKeyException * @throws NoSuchAlgorithmException * @throws KeyStoreException */ public Crypter_Blowfish(final KeyStore keyStore, final char[] keystorepass, final String alias) throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException { this(keyStore.getKey(alias, keystorepass).getEncoded()); } /** * @param keyStore * @param keystorepass * @param alias * @param cipher * @throws UnrecoverableKeyException * @throws NoSuchAlgorithmException * @throws KeyStoreException */ public Crypter_Blowfish(final KeyStore keyStore, final char[] keystorepass, final String alias, final String cipher) throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException { this(keyStore.getKey(alias, keystorepass).getEncoded(), cipher); } /** * @param keyStore * @param keystorepass * @param alias * @param cipher * @param salter * @throws UnrecoverableKeyException * @throws NoSuchAlgorithmException * @throws KeyStoreException */ public Crypter_Blowfish(final KeyStore keyStore, final char[] keystorepass, final String alias, final String cipher, final SecureRandom salter) throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException { this(keyStore.getKey(alias, keystorepass).getEncoded(), cipher, salter); } public Crypter_Blowfish(final File keyfile) throws NoSuchAlgorithmException, IOException { this(FileUtils.readFileToByteArray(keyfile)); } /** * @param keyfile * @param cipher * @throws NoSuchAlgorithmException * @throws IOException */ public Crypter_Blowfish(final File keyfile, final String cipher) throws NoSuchAlgorithmException, IOException { this(FileUtils.readFileToByteArray(keyfile), cipher); } /** * @param keyfile * @param cipher * @param salter * @throws IOException */ public Crypter_Blowfish(final File keyfile, final String cipher, final SecureRandom salter) throws IOException { this(FileUtils.readFileToByteArray(keyfile), cipher, salter); } /** * @param keystream * @throws NoSuchAlgorithmException * @throws IOException */ public Crypter_Blowfish(final InputStream keystream) throws NoSuchAlgorithmException, IOException { this(IOUtils.toByteArray(keystream)); } /** * @param keystream * @param cipher * @throws NoSuchAlgorithmException * @throws IOException */ public Crypter_Blowfish(final InputStream keystream, final String cipher) throws NoSuchAlgorithmException, IOException { this(IOUtils.toByteArray(keystream), cipher); } /** * @param keystream * @param cipher * @param salter * @throws IOException */ public Crypter_Blowfish(final InputStream keystream, final String cipher, final SecureRandom salter) throws IOException { this(IOUtils.toByteArray(keystream), cipher, salter); } /** * @param key * @throws NoSuchAlgorithmException */ public Crypter_Blowfish(final byte[] key) throws NoSuchAlgorithmException { this(key, mycipher, (SecureRandom) null); } /** * @param key * @param cipher * @throws NoSuchAlgorithmException */ public Crypter_Blowfish(final byte[] key, final String cipher) throws NoSuchAlgorithmException { this(key, cipher, (SecureRandom) null); } /** * @param key * @param cipher * @param salter */ public Crypter_Blowfish(final byte[] key, final String cipher, final SecureRandom salter) { super(mytype, cipher, salter); this.key = key; this.secretkey = new SecretKeySpec(key, 0, key.length, super.getType()); } /* (non-Javadoc) * @see com.zacwolf.commons.crypto.Crypter#getDcipher(byte[]) */ @Override final Cipher getDcipher(byte[] salt) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { final Cipher dcipher = Cipher.getInstance(this.cipher); dcipher.init(Cipher.DECRYPT_MODE, this.secretkey, getAlgorithmParameterSpec(salt), this.salter); return dcipher; } /* (non-Javadoc) * @see com.zacwolf.commons.crypto.Crypter#getEcipher() */ @Override final Cipher getEcipher() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { final Cipher ecipher = Cipher.getInstance(this.cipher); ecipher.init(Cipher.ENCRYPT_MODE, this.secretkey, getAlgorithmParameterSpec(), super.salter); return ecipher; } /* (non-Javadoc) * @see com.zacwolf.commons.crypto.Crypter#addToKeystore(java.security.KeyStore, char[], java.lang.String) */ @Override public final void addToKeystore(final KeyStore keystore, final char[] keystorepass, final String alias) throws KeyStoreException, CertificateException { keystore.setKeyEntry(alias == null ? super.type : alias, this.secretkey, keystorepass, null); } /* (non-Javadoc) * @see com.zacwolf.commons.crypto.Crypter#getCHKey() */ @Override public byte[] getCHKey() throws IOException { return super.getCHKey(this.key); } /* (non-Javadoc) * @see com.zacwolf.commons.crypto.Crypter#getNewSalt() */ @Override byte[] getNewSalt() { final byte[] bytes = new byte[8]; super.salter.nextBytes(bytes); return bytes; } /** * Creates a new new key with the default keysize specified by mykeysizemax * * @param keyfile * @throws NoSuchAlgorithmException * @throws IOException * @throws InvalidKeySpecException */ public final static void generateNewKeyFile(File keyfile) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException { generateNewKeyFile(keyfile, Cipher.getMaxAllowedKeyLength(mytype), Crypter.defaultsalter); } /** * Create a new key with the default keysize specified by mykeysizemax, * specifying a custom salter * * @param keyfile * @param salter * @throws NoSuchAlgorithmException * @throws IOException * @throws InvalidKeySpecException */ public final static void generateNewKeyFile(File keyfile, final SecureRandom salter) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException { generateNewKeyFile(keyfile, Cipher.getMaxAllowedKeyLength(mytype), salter); } /** * Create a new key with a custom keysize less-than equal to mykeysizemax * * @param keyfile * @param keysize * @throws NoSuchAlgorithmException * @throws IOException * @throws InvalidKeySpecException */ public final static void generateNewKeyFile(File keyfile, final int keysize) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException { generateNewKeyFile(keyfile, keysize, Crypter.defaultsalter); } /** * * Create a new key with a custom keysize less-than equal to mykeysizemax, * specifying a custom salter * * @param keyfile * @param keysize * @param salter * @throws NoSuchAlgorithmException * @throws IOException * @throws InvalidKeySpecException */ public final static void generateNewKeyFile(final File keyfile, final int keysize, final SecureRandom salter) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException { if (keysize > Cipher.getMaxAllowedKeyLength(mytype)) throw new InvalidKeySpecException( "You specified a key size not supported by your current cryptographic libraries, which currently have a max key size of " + Cipher.getMaxAllowedKeyLength(mytype) + " for " + mytype); final FileOutputStream fos = new FileOutputStream(keyfile); try { final KeyGenerator kgen = KeyGenerator.getInstance(mytype); kgen.init(keysize > mykeysizemax ? mykeysizemax : keysize, salter); // 192 and 256 bits may not be available final SecretKey sk = kgen.generateKey(); fos.write(sk.getEncoded()); } finally { if (fos != null) { fos.flush(); fos.close(); } } } }