1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.ssl;
17
18 import java.io.ByteArrayOutputStream;
19 import java.util.zip.DataFormatException;
20 import java.util.zip.Deflater;
21 import java.util.zip.Inflater;
22 import javax.net.ssl.SSLEngine;
23
24
25
26
27
28
29
30
31 public final class ZlibCertificateCompressionAlgorithm implements OpenSslCertificateCompressionAlgorithm {
32
33
34
35 public static final ZlibCertificateCompressionAlgorithm INSTANCE = new ZlibCertificateCompressionAlgorithm();
36
37
38 private static final int ALGORITHM_ID = 1;
39 private static final int BUFFER_SIZE = 8192;
40 private static final int MAX_UNCOMPRESSED_CERTIFICATE_LENGTH = 0xFFFFFF;
41
42 private ZlibCertificateCompressionAlgorithm() { }
43
44 @Override
45 public byte[] compress(SSLEngine engine, byte[] uncompressedCertificate) {
46 Deflater deflater = new Deflater();
47 try {
48 deflater.setInput(uncompressedCertificate);
49 deflater.finish();
50 ByteArrayOutputStream output = new ByteArrayOutputStream(uncompressedCertificate.length);
51 byte[] buffer = new byte[BUFFER_SIZE];
52 while (!deflater.finished()) {
53 int length = deflater.deflate(buffer);
54 output.write(buffer, 0, length);
55 }
56 return output.toByteArray();
57 } finally {
58 deflater.end();
59 }
60 }
61
62 @Override
63 public byte[] decompress(SSLEngine engine, int uncompressedLen, byte[] compressedCertificate)
64 throws DataFormatException {
65 if (uncompressedLen < 0 || uncompressedLen > MAX_UNCOMPRESSED_CERTIFICATE_LENGTH) {
66 throw new DataFormatException("uncompressed length must be between 0 and " +
67 MAX_UNCOMPRESSED_CERTIFICATE_LENGTH);
68 }
69
70 Inflater inflater = new Inflater();
71 try {
72 inflater.setInput(compressedCertificate);
73 byte[] output = new byte[uncompressedLen];
74 int offset = 0;
75 while (!inflater.finished() && offset < output.length) {
76 int length = inflater.inflate(output, offset, output.length - offset);
77 if (length == 0) {
78 break;
79 }
80 offset += length;
81 }
82 if (!inflater.finished() || offset != uncompressedLen || inflater.getRemaining() != 0) {
83 throw new DataFormatException("decompressed certificate length does not match uncompressed length");
84 }
85 return output;
86 } finally {
87 inflater.end();
88 }
89 }
90
91 @Override
92 public int algorithmId() {
93 return ALGORITHM_ID;
94 }
95 }