001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.commons.compress.archivers.zip; 020 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.Map; 024 025/** 026 * Base class for all PKWare strong crypto extra headers. 027 * 028 * <p>This base class acts as a marker so you know you can ignore all 029 * extra fields that extend this class if you are not interested in 030 * the meta data of PKWare strong encryption.</p> 031 * 032 * <b>Algorithm IDs</b> - integer identifier of the encryption algorithm from 033 * the following range 034 * 035 * <ul> 036 * <li>0x6601 - DES</li> 037 * <li>0x6602 - RC2 (version needed to extract < 5.2)</li> 038 * <li>0x6603 - 3DES 168</li> 039 * <li>0x6609 - 3DES 112</li> 040 * <li>0x660E - AES 128</li> 041 * <li>0x660F - AES 192</li> 042 * <li>0x6610 - AES 256</li> 043 * <li>0x6702 - RC2 (version needed to extract >= 5.2)</li> 044 * <li>0x6720 - Blowfish</li> 045 * <li>0x6721 - Twofish</li> 046 * <li>0x6801 - RC4</li> 047 * <li>0xFFFF - Unknown algorithm</li> 048 * </ul> 049 * 050 * <b>Hash Algorithms</b> - integer identifier of the hash algorithm from the 051 * following range 052 * 053 * <ul> 054 * <li>0x0000 - none</li> 055 * <li>0x0001 - CRC32</li> 056 * <li>0x8003 - MD5</li> 057 * <li>0x8004 - SHA1</li> 058 * <li>0x8007 - RIPEMD160</li> 059 * <li>0x800C - SHA256</li> 060 * <li>0x800D - SHA384</li> 061 * <li>0x800E - SHA512</li> 062 * </ul> 063 * 064 * @since 1.11 065 */ 066public abstract class PKWareExtraHeader implements ZipExtraField { 067 068 private final ZipShort headerId; 069 /** 070 * Extra field data in local file data - without Header-ID or length 071 * specifier. 072 */ 073 private byte[] localData; 074 /** 075 * Extra field data in central directory - without Header-ID or length 076 * specifier. 077 */ 078 private byte[] centralData; 079 080 protected PKWareExtraHeader(ZipShort headerId) { 081 this.headerId = headerId; 082 } 083 084 /** 085 * Get the header id. 086 * 087 * @return the header id 088 */ 089 public ZipShort getHeaderId() { 090 return headerId; 091 } 092 093 /** 094 * Set the extra field data in the local file data - without Header-ID or 095 * length specifier. 096 * 097 * @param data 098 * the field data to use 099 */ 100 public void setLocalFileDataData(byte[] data) { 101 localData = ZipUtil.copy(data); 102 } 103 104 /** 105 * Get the length of the local data. 106 * 107 * @return the length of the local data 108 */ 109 public ZipShort getLocalFileDataLength() { 110 return new ZipShort(localData != null ? localData.length : 0); 111 } 112 113 /** 114 * Get the local data. 115 * 116 * @return the local data 117 */ 118 public byte[] getLocalFileDataData() { 119 return ZipUtil.copy(localData); 120 } 121 122 /** 123 * Set the extra field data in central directory. 124 * 125 * @param data 126 * the data to use 127 */ 128 public void setCentralDirectoryData(byte[] data) { 129 centralData = ZipUtil.copy(data); 130 } 131 132 /** 133 * Get the central data length. If there is no central data, get the local 134 * file data length. 135 * 136 * @return the central data length 137 */ 138 public ZipShort getCentralDirectoryLength() { 139 if (centralData != null) { 140 return new ZipShort(centralData.length); 141 } 142 return getLocalFileDataLength(); 143 } 144 145 /** 146 * Get the central data. 147 * 148 * @return the central data if present, else return the local file data 149 */ 150 public byte[] getCentralDirectoryData() { 151 if (centralData != null) { 152 return ZipUtil.copy(centralData); 153 } 154 return getLocalFileDataData(); 155 } 156 157 /** 158 * @param data 159 * the array of bytes. 160 * @param offset 161 * the source location in the data array. 162 * @param length 163 * the number of bytes to use in the data array. 164 * @see ZipExtraField#parseFromLocalFileData(byte[], int, int) 165 */ 166 public void parseFromLocalFileData(byte[] data, int offset, int length) { 167 byte[] tmp = new byte[length]; 168 System.arraycopy(data, offset, tmp, 0, length); 169 setLocalFileDataData(tmp); 170 } 171 172 /** 173 * @param data 174 * the array of bytes. 175 * @param offset 176 * the source location in the data array. 177 * @param length 178 * the number of bytes to use in the data array. 179 * @see ZipExtraField#parseFromCentralDirectoryData(byte[], int, int) 180 */ 181 public void parseFromCentralDirectoryData(byte[] data, int offset, int length) { 182 byte[] tmp = new byte[length]; 183 System.arraycopy(data, offset, tmp, 0, length); 184 setCentralDirectoryData(tmp); 185 if (localData == null) { 186 setLocalFileDataData(tmp); 187 } 188 } 189 190 /** 191 * Encryption algorithm. 192 * 193 * @since 1.11 194 */ 195 public enum EncryptionAlgorithm { 196 DES(0x6601), 197 RC2pre52(0x6602), 198 TripleDES168(0x6603), 199 TripleDES192(0x6609), 200 AES128(0x660E), 201 AES192(0x660F), 202 AES256(0x6610), 203 RC2(0x6702), 204 RC4(0x6801), 205 UNKNOWN(0xFFFF); 206 207 private final int code; 208 209 private static final Map<Integer, EncryptionAlgorithm> codeToEnum; 210 211 static { 212 Map<Integer, EncryptionAlgorithm> cte = new HashMap<Integer, EncryptionAlgorithm>(); 213 for (EncryptionAlgorithm method : values()) { 214 cte.put(Integer.valueOf(method.getCode()), method); 215 } 216 codeToEnum = Collections.unmodifiableMap(cte); 217 } 218 219 /** 220 * private constructor for enum style class. 221 */ 222 EncryptionAlgorithm(int code) { 223 this.code = code; 224 } 225 226 /** 227 * the algorithm id. 228 * 229 * @return the PKWare AlgorithmId 230 */ 231 public int getCode() { 232 return code; 233 } 234 235 /** 236 * Returns the EncryptionAlgorithm for the given code or null if the 237 * method is not known. 238 * @param code the code of the algorithm 239 * @return the EncryptionAlgorithm for the given code or null 240 * if the method is not known 241 */ 242 public static EncryptionAlgorithm getAlgorithmByCode(int code) { 243 return codeToEnum.get(Integer.valueOf(code)); 244 } 245 } 246 247 /** 248 * Hash Algorithm 249 * 250 * @since 1.11 251 */ 252 public enum HashAlgorithm { 253 NONE(0), 254 CRC32(1), 255 MD5(0x8003), 256 SHA1(0x8004), 257 RIPEND160(0x8007), 258 SHA256(0x800C), 259 SHA384(0x800D), 260 SHA512(0x800E); 261 262 private final int code; 263 264 private static final Map<Integer, HashAlgorithm> codeToEnum; 265 266 static { 267 Map<Integer, HashAlgorithm> cte = new HashMap<Integer, HashAlgorithm>(); 268 for (HashAlgorithm method : values()) { 269 cte.put(Integer.valueOf(method.getCode()), method); 270 } 271 codeToEnum = Collections.unmodifiableMap(cte); 272 } 273 274 /** 275 * private constructor for enum style class. 276 */ 277 HashAlgorithm(int code) { 278 this.code = code; 279 } 280 281 /** 282 * the hash algorithm ID. 283 * 284 * @return the PKWare hashAlg 285 */ 286 public int getCode() { 287 return code; 288 } 289 290 /** 291 * Returns the HashAlgorithm for the given code or null if the method is 292 * not known. 293 * @param code the code of the algorithm 294 * @return the HashAlgorithm for the given code or null 295 * if the method is not known 296 */ 297 public static HashAlgorithm getAlgorithmByCode(int code) { 298 return codeToEnum.get(Integer.valueOf(code)); 299 } 300 } 301}