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.security.PrivateKey;
19
20 import javax.security.auth.Destroyable;
21
22 import io.netty.buffer.ByteBuf;
23 import io.netty.buffer.ByteBufAllocator;
24 import io.netty.buffer.Unpooled;
25 import io.netty.util.AbstractReferenceCounted;
26 import io.netty.util.CharsetUtil;
27 import io.netty.util.IllegalReferenceCountException;
28 import io.netty.util.internal.ObjectUtil;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 public final class PemPrivateKey extends AbstractReferenceCounted implements PrivateKey, PemEncoded {
44 private static final long serialVersionUID = 7978017465645018936L;
45
46 private static final byte[] BEGIN_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n".getBytes(CharsetUtil.US_ASCII);
47 private static final byte[] END_PRIVATE_KEY = "\n-----END PRIVATE KEY-----\n".getBytes(CharsetUtil.US_ASCII);
48
49 private static final String PKCS8_FORMAT = "PKCS#8";
50
51
52
53
54 static PemEncoded toPEM(ByteBufAllocator allocator, boolean useDirect, PrivateKey key) {
55
56
57
58
59 if (key instanceof PemEncoded) {
60 return ((PemEncoded) key).retain();
61 }
62
63 ByteBuf encoded = Unpooled.wrappedBuffer(key.getEncoded());
64 try {
65 ByteBuf base64 = SslUtils.toBase64(allocator, encoded);
66 try {
67 int size = BEGIN_PRIVATE_KEY.length + base64.readableBytes() + END_PRIVATE_KEY.length;
68
69 boolean success = false;
70 final ByteBuf pem = useDirect ? allocator.directBuffer(size) : allocator.buffer(size);
71 try {
72 pem.writeBytes(BEGIN_PRIVATE_KEY);
73 pem.writeBytes(base64);
74 pem.writeBytes(END_PRIVATE_KEY);
75
76 PemValue value = new PemValue(pem, true);
77 success = true;
78 return value;
79 } finally {
80
81 if (!success) {
82 SslUtils.zerooutAndRelease(pem);
83 }
84 }
85 } finally {
86 SslUtils.zerooutAndRelease(base64);
87 }
88 } finally {
89 SslUtils.zerooutAndRelease(encoded);
90 }
91 }
92
93
94
95
96
97
98
99 public static PemPrivateKey valueOf(byte[] key) {
100 return valueOf(Unpooled.wrappedBuffer(key));
101 }
102
103
104
105
106
107
108
109 public static PemPrivateKey valueOf(ByteBuf key) {
110 return new PemPrivateKey(key);
111 }
112
113 private final ByteBuf content;
114
115 private PemPrivateKey(ByteBuf content) {
116 this.content = ObjectUtil.checkNotNull(content, "content");
117 }
118
119 @Override
120 public boolean isSensitive() {
121 return true;
122 }
123
124 @Override
125 public ByteBuf content() {
126 int count = refCnt();
127 if (count <= 0) {
128 throw new IllegalReferenceCountException(count);
129 }
130
131 return content;
132 }
133
134 @Override
135 public PemPrivateKey copy() {
136 return new PemPrivateKey(content.copy());
137 }
138
139 @Override
140 public PemPrivateKey duplicate() {
141 return new PemPrivateKey(content.duplicate());
142 }
143
144 @Override
145 public PemPrivateKey retain() {
146 return (PemPrivateKey) super.retain();
147 }
148
149 @Override
150 public PemPrivateKey retain(int increment) {
151 return (PemPrivateKey) super.retain(increment);
152 }
153
154 @Override
155 protected void deallocate() {
156
157
158 SslUtils.zerooutAndRelease(content);
159 }
160
161 @Override
162 public byte[] getEncoded() {
163 throw new UnsupportedOperationException();
164 }
165
166 @Override
167 public String getAlgorithm() {
168 throw new UnsupportedOperationException();
169 }
170
171 @Override
172 public String getFormat() {
173 return PKCS8_FORMAT;
174 }
175
176
177
178
179
180
181
182
183 public void destroy() {
184 release(refCnt());
185 }
186
187
188
189
190
191
192
193
194 public boolean isDestroyed() {
195 return refCnt() == 0;
196 }
197 }