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(final ZipShort headerId) { 081 this.headerId = headerId; 082 } 083 084 /** 085 * Get the header id. 086 * 087 * @return the header id 088 */ 089 @Override 090 public ZipShort getHeaderId() { 091 return headerId; 092 } 093 094 /** 095 * Set the extra field data in the local file data - without Header-ID or 096 * length specifier. 097 * 098 * @param data 099 * the field data to use 100 */ 101 public void setLocalFileDataData(final byte[] data) { 102 localData = ZipUtil.copy(data); 103 } 104 105 /** 106 * Get the length of the local data. 107 * 108 * @return the length of the local data 109 */ 110 @Override 111 public ZipShort getLocalFileDataLength() { 112 return new ZipShort(localData != null ? localData.length : 0); 113 } 114 115 /** 116 * Get the local data. 117 * 118 * @return the local data 119 */ 120 @Override 121 public byte[] getLocalFileDataData() { 122 return ZipUtil.copy(localData); 123 } 124 125 /** 126 * Set the extra field data in central directory. 127 * 128 * @param data 129 * the data to use 130 */ 131 public void setCentralDirectoryData(final byte[] data) { 132 centralData = ZipUtil.copy(data); 133 } 134 135 /** 136 * Get the central data length. If there is no central data, get the local 137 * file data length. 138 * 139 * @return the central data length 140 */ 141 @Override 142 public ZipShort getCentralDirectoryLength() { 143 if (centralData != null) { 144 return new ZipShort(centralData.length); 145 } 146 return getLocalFileDataLength(); 147 } 148 149 /** 150 * Get the central data. 151 * 152 * @return the central data if present, else return the local file data 153 */ 154 @Override 155 public byte[] getCentralDirectoryData() { 156 if (centralData != null) { 157 return ZipUtil.copy(centralData); 158 } 159 return getLocalFileDataData(); 160 } 161 162 /** 163 * @param data 164 * the array of bytes. 165 * @param offset 166 * the source location in the data array. 167 * @param length 168 * the number of bytes to use in the data array. 169 * @see ZipExtraField#parseFromLocalFileData(byte[], int, int) 170 */ 171 @Override 172 public void parseFromLocalFileData(final byte[] data, final int offset, final int length) { 173 final byte[] tmp = new byte[length]; 174 System.arraycopy(data, offset, tmp, 0, length); 175 setLocalFileDataData(tmp); 176 } 177 178 /** 179 * @param data 180 * the array of bytes. 181 * @param offset 182 * the source location in the data array. 183 * @param length 184 * the number of bytes to use in the data array. 185 * @see ZipExtraField#parseFromCentralDirectoryData(byte[], int, int) 186 */ 187 @Override 188 public void parseFromCentralDirectoryData(final byte[] data, final int offset, final int length) { 189 final byte[] tmp = new byte[length]; 190 System.arraycopy(data, offset, tmp, 0, length); 191 setCentralDirectoryData(tmp); 192 if (localData == null) { 193 setLocalFileDataData(tmp); 194 } 195 } 196 197 /** 198 * Encryption algorithm. 199 * 200 * @since 1.11 201 */ 202 public enum EncryptionAlgorithm { 203 DES(0x6601), 204 RC2pre52(0x6602), 205 TripleDES168(0x6603), 206 TripleDES192(0x6609), 207 AES128(0x660E), 208 AES192(0x660F), 209 AES256(0x6610), 210 RC2(0x6702), 211 RC4(0x6801), 212 UNKNOWN(0xFFFF); 213 214 private final int code; 215 216 private static final Map<Integer, EncryptionAlgorithm> codeToEnum; 217 218 static { 219 final Map<Integer, EncryptionAlgorithm> cte = new HashMap<>(); 220 for (final EncryptionAlgorithm method : values()) { 221 cte.put(method.getCode(), method); 222 } 223 codeToEnum = Collections.unmodifiableMap(cte); 224 } 225 226 /** 227 * private constructor for enum style class. 228 */ 229 EncryptionAlgorithm(final int code) { 230 this.code = code; 231 } 232 233 /** 234 * the algorithm id. 235 * 236 * @return the PKWare AlgorithmId 237 */ 238 public int getCode() { 239 return code; 240 } 241 242 /** 243 * Returns the EncryptionAlgorithm for the given code or null if the 244 * method is not known. 245 * @param code the code of the algorithm 246 * @return the EncryptionAlgorithm for the given code or null 247 * if the method is not known 248 */ 249 public static EncryptionAlgorithm getAlgorithmByCode(final int code) { 250 return codeToEnum.get(code); 251 } 252 } 253 254 /** 255 * Hash Algorithm 256 * 257 * @since 1.11 258 */ 259 public enum HashAlgorithm { 260 NONE(0), 261 CRC32(1), 262 MD5(0x8003), 263 SHA1(0x8004), 264 RIPEND160(0x8007), 265 SHA256(0x800C), 266 SHA384(0x800D), 267 SHA512(0x800E); 268 269 private final int code; 270 271 private static final Map<Integer, HashAlgorithm> codeToEnum; 272 273 static { 274 final Map<Integer, HashAlgorithm> cte = new HashMap<>(); 275 for (final HashAlgorithm method : values()) { 276 cte.put(method.getCode(), method); 277 } 278 codeToEnum = Collections.unmodifiableMap(cte); 279 } 280 281 /** 282 * private constructor for enum style class. 283 */ 284 HashAlgorithm(final int code) { 285 this.code = code; 286 } 287 288 /** 289 * the hash algorithm ID. 290 * 291 * @return the PKWare hashAlg 292 */ 293 public int getCode() { 294 return code; 295 } 296 297 /** 298 * Returns the HashAlgorithm for the given code or null if the method is 299 * not known. 300 * @param code the code of the algorithm 301 * @return the HashAlgorithm for the given code or null 302 * if the method is not known 303 */ 304 public static HashAlgorithm getAlgorithmByCode(final int code) { 305 return codeToEnum.get(code); 306 } 307 } 308}