001/* 002 * Syncany, www.syncany.org 003 * Copyright (C) 2011-2016 Philipp C. Heckel <philipp.heckel@gmail.com> 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU General Public License as published by 007 * the Free Software Foundation, either version 3 of the License, or 008 * (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 General Public License for more details. 014 * 015 * You should have received a copy of the GNU General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018package org.syncany.crypto; 019 020import java.util.ArrayList; 021import java.util.List; 022import java.util.Map; 023import java.util.TreeMap; 024 025import org.syncany.crypto.specs.AesGcm128CipherSpec; 026import org.syncany.crypto.specs.AesGcm256CipherSpec; 027import org.syncany.crypto.specs.TwofishGcm128CipherSpec; 028import org.syncany.crypto.specs.TwofishGcm256CipherSpec; 029 030/** 031 * Defines and identifies the application supported {@link CipherSpec}s. 032 * 033 * <p>These cipher specs are used by the {@link MultiCipherOutputStream} to encrypt 034 * data, and by the {@link MultiCipherInputStream} to decrypt data. The cipher spec 035 * identifiers are used in the crypto format header to identify the crypto algorithms 036 * used for encryption. 037 * 038 * <p>The class defines a well defined (and developer-approved) set of allowed 039 * cipher algorithms, modes and key sizes. The number of allowed ciphers is greatly 040 * restricted to follow the application-specific security standards. Most prominently, 041 * this includes: 042 * 043 * <ul> 044 * <li>The block cipher mode must be authenticated (GCM, EAX, etc.). Unauthenticated 045 * modes are not supported and will be rejected by the {@link CipherSpec} sanity checks. 046 * <li>The block cipher mode must require an initialization vector (IV). Modes that do 047 * not require an IV (e.g. ECB) will be rejected by the {@link CipherSpec} sanity checks. 048 * </ul> 049 * 050 * @author Philipp C. Heckel (philipp.heckel@gmail.com) 051 */ 052public class CipherSpecs { 053 private static final Map<Integer, CipherSpec> cipherSpecs = new TreeMap<Integer, CipherSpec>(); 054 055 /* 056 * WARNING: The cipher spec identifiers are written to the MultiCipherOutputStream and read by the MultiCipherInputStream. The identifiers MUST 057 * NOT be changed, because this will make decryption of already encrypted data impossible! 058 */ 059 public static final int AES_128_GCM = 0x01; 060 public static final int TWOFISH_128_GCM = 0x02; 061 public static final int AES_256_GCM = 0x03; 062 public static final int TWOFISH_256_GCM = 0x04; 063 064 public static final int[] DEFAULT_CIPHER_SPECS = new int[] { CipherSpecs.AES_128_GCM }; 065 066 static { 067 CipherSpec[] tmpCipherSpecs = new CipherSpec[] { 068 // Standard 069 new AesGcm128CipherSpec(), 070 new TwofishGcm128CipherSpec(), 071 072 // Unlimited crypto 073 new AesGcm256CipherSpec(), 074 new TwofishGcm256CipherSpec() 075 }; 076 077 for (CipherSpec cipherSpec : tmpCipherSpecs) { 078 registerCipherSpec(cipherSpec.getId(), cipherSpec); 079 } 080 } 081 082 /** 083 * Returns a list of available/registered {@link CipherSpec}s. Refer to the 084 * {@link CipherSpecs class description} for a more detailed explanation. 085 */ 086 public static Map<Integer, CipherSpec> getAvailableCipherSpecs() { 087 return cipherSpecs; 088 } 089 090 /** 091 * Returns the default {@link CipherSpec}s used by the application. 092 */ 093 public static List<CipherSpec> getDefaultCipherSpecs() { 094 List<CipherSpec> cipherSpecs = new ArrayList<CipherSpec>(); 095 096 for (int cipherSpecId : DEFAULT_CIPHER_SPECS) { 097 cipherSpecs.add(getCipherSpec(cipherSpecId)); 098 } 099 100 return cipherSpecs; 101 } 102 103 /** 104 * Retrieves an available/registered {@link CipherSpec} using the cipher spec identifier 105 * defined in this class. 106 * 107 * @param id Identifier of the cipher spec 108 * @return A cipher spec, or <code>null</code> if no cipher spec with this identifier is registered 109 */ 110 public static CipherSpec getCipherSpec(int id) { 111 return cipherSpecs.get(id); 112 } 113 114 /** 115 * Register a new cipher spec. 116 * 117 * <p>Note: Registering a cipher spec locally does not make it available on all clients. Unless 118 * a cipher spec is registered before a client tries to decrypt data using the {@link MultiCipherInputStream}, 119 * the decryption process will fail. 120 * 121 * @param id Identifier of the cipher spec 122 */ 123 public static void registerCipherSpec(int id, CipherSpec cipherSpec) { 124 cipherSpecs.put(id, cipherSpec); 125 } 126}