1
2
3
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
15
16
17
18
19
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
30
31
32
33 static final int VV_AE_1 = 1;
34
35
36
37
38
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
62
63
64
65
66 int getVendorVersion() { return vendorVersion & UShort.MAX_VALUE; }
67
68
69
70
71
72
73
74
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]));
108 off += 1;
109 setMethod(readUShort(buf, off));
110
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
123 }
124 }