View Javadoc
1   /*
2    * Copyright (C) 2005-2015 Schlichtherle IT Services.
3    * All rights reserved. Use is subject to license terms.
4    */
5   package net.java.truevfs.comp.zip;
6   
7   import javax.annotation.concurrent.NotThreadSafe;
8   import net.java.truecommons.key.spec.common.AesKeyStrength;
9   import static net.java.truecommons.key.spec.common.AesKeyStrength.BITS_128;
10  import static net.java.truevfs.comp.zip.LittleEndian.readUShort;
11  import static net.java.truevfs.comp.zip.LittleEndian.writeShort;
12  
13  /**
14   * WinZip AES Extra Field.
15   *
16   * @see     <a href="http://www.winzip.com/win/en/aes_info.htm">AES Encryption Information: Encryption Specification AE-1 and AE-2 (WinZip Computing, S.L.)</a>
17   * @see     <a href="http://www.winzip.com/win/en/aes_tips.htm">AES Coding Tips for Developers (WinZip Computing, S.L.)</a>
18   * @see     RawZipOutputStream$WinZipAesOutputMethod
19   * @author  Christian Schlichtherle
20   */
21  @NotThreadSafe
22  final class WinZipAesExtraField extends ExtraField {
23  
24      private static final int DATA_SIZE = 7;
25      private static final int VENDOR_ID = 'A' | ('E' << 8);
26      private static final AesKeyStrength[] KEY_STRENGTHS = AesKeyStrength.values();
27  
28      /**
29       * Entries of this type <em>do</em> include the standard ZIP CRC-32
30       * value.
31       * For use with {@link #setVendorVersion(int)}/{@link #getVendorVersion()}.
32       */
33      static final int VV_AE_1 = 1;
34  
35      /**
36       * Entries of this type do <em>not</em> include the standard ZIP CRC-32
37       * value.
38       * For use with {@link #setVendorVersion(int)}/{@link #getVendorVersion()}.
39       */
40      static final int VV_AE_2 = 2;
41  
42      private short vendorVersion = VV_AE_1;
43      private byte encryptionStrength = encryptionStrength(BITS_128);
44      private short method;
45  
46      private static byte encryptionStrength(AesKeyStrength keyStrength) {
47          return (byte) (keyStrength.ordinal() + 1);
48      }
49  
50      private static AesKeyStrength keyStrength(int encryptionStrength) {
51          return KEY_STRENGTHS[(encryptionStrength - 1) & UByte.MAX_VALUE];
52      }
53  
54      @Override
55      int getHeaderId() { return WINZIP_AES_ID; }
56  
57      @Override
58      int getDataSize() { return DATA_SIZE; }
59  
60      /**
61       * Returns the vendor version.
62       *
63       * @see #VV_AE_1
64       * @see #VV_AE_2
65       */
66      int getVendorVersion() { return vendorVersion & UShort.MAX_VALUE; }
67  
68      /**
69       * Sets the vendor version.
70       *
71       * @see    #VV_AE_1
72       * @see    #VV_AE_2
73       * @param  vendorVersion the vendor version.
74       * @throws IllegalArgumentException
75       */
76      void setVendorVersion(final int vendorVersion) {
77          if (vendorVersion < VV_AE_1 || VV_AE_2 < vendorVersion)
78              throw new IllegalArgumentException("" + vendorVersion);
79          this.vendorVersion = (short) vendorVersion;
80      }
81  
82      int getVendorId() { return VENDOR_ID; }
83  
84      AesKeyStrength getKeyStrength() {
85          return keyStrength(this.encryptionStrength);
86      }
87  
88      void setKeyStrength(final AesKeyStrength keyStrength) {
89          this.encryptionStrength = encryptionStrength(keyStrength);
90      }
91  
92      int getMethod() { return method & UShort.MAX_VALUE; }
93  
94      void setMethod(final int compressionMethod) {
95          assert UShort.check(compressionMethod);
96          this.method = (short) compressionMethod;
97      }
98  
99      @Override
100     void readFrom(final byte[] buf, int off, final int len) {
101         if (DATA_SIZE != len) throw new IllegalArgumentException();
102         setVendorVersion(readUShort(buf, off));
103         off += 2;
104         final int vendorId = (short) readUShort(buf, off);
105         off += 2;
106         if (VENDOR_ID != vendorId) throw new IllegalArgumentException();
107         setKeyStrength(keyStrength(buf[off])); // checked
108         off += 1;
109         setMethod(readUShort(buf, off));
110         // off += 2;
111     }
112 
113     @Override
114     void writeTo(byte[] buf, int off) {
115         writeShort(this.vendorVersion, buf, off);
116         off += 2;
117         writeShort(VENDOR_ID, buf, off);
118         off += 2;
119         buf[off] = this.encryptionStrength;
120         off += 1;
121         writeShort(this.method, buf, off);
122         // off += 2;
123     }
124 }