1818
1919import static com .google .common .base .Preconditions .checkArgument ;
2020
21- import com .google .common .collect .ImmutableMap ;
22- import com .google .common .hash .Hashing ;
23- import com .google .common .net .UrlEscapers ;
2421import java .net .URI ;
25- import java .nio .charset .StandardCharsets ;
26- import java .text .SimpleDateFormat ;
27- import java .util .Date ;
28- import java .util .HashMap ;
2922import java .util .Map ;
30- import java .util .TimeZone ;
3123
3224/**
3325 * Signature Info holds payload components of the string that requires signing.
3931public class SignatureInfo {
4032
4133 public static final char COMPONENT_SEPARATOR = '\n' ;
42- public static final String GOOG4_RSA_SHA256 = "GOOG4-RSA-SHA256" ;
43- public static final String SCOPE = "/auto/storage/goog4_request" ;
4434
4535 private final HttpMethod httpVerb ;
4636 private final String contentMd5 ;
4737 private final String contentType ;
4838 private final long expiration ;
4939 private final Map <String , String > canonicalizedExtensionHeaders ;
5040 private final URI canonicalizedResource ;
51- private final Storage .SignUrlOption .SignatureVersion signatureVersion ;
52- private final String accountEmail ;
53- private final long timestamp ;
54-
55- private final String yearMonthDay ;
56- private final String exactDate ;
5741
5842 private SignatureInfo (Builder builder ) {
5943 this .httpVerb = builder .httpVerb ;
6044 this .contentMd5 = builder .contentMd5 ;
6145 this .contentType = builder .contentType ;
6246 this .expiration = builder .expiration ;
47+ this .canonicalizedExtensionHeaders = builder .canonicalizedExtensionHeaders ;
6348 this .canonicalizedResource = builder .canonicalizedResource ;
64- this .signatureVersion = builder .signatureVersion ;
65- this .accountEmail = builder .accountEmail ;
66- this .timestamp = builder .timestamp ;
67-
68- if (Storage .SignUrlOption .SignatureVersion .V4 .equals (signatureVersion )
69- && (!builder .canonicalizedExtensionHeaders .containsKey ("host" ))) {
70- canonicalizedExtensionHeaders =
71- new ImmutableMap .Builder <String , String >()
72- .putAll (builder .canonicalizedExtensionHeaders )
73- .put ("host" , "storage.googleapis.com" )
74- .build ();
75- } else {
76- canonicalizedExtensionHeaders = builder .canonicalizedExtensionHeaders ;
77- }
78-
79- Date date = new Date (timestamp );
80-
81- SimpleDateFormat yearMonthDayFormat = new SimpleDateFormat ("yyyyMMdd" );
82- SimpleDateFormat exactDateFormat = new SimpleDateFormat ("yyyyMMdd'T'HHmmss'Z'" );
83-
84- yearMonthDayFormat .setTimeZone (TimeZone .getTimeZone ("UTC" ));
85- exactDateFormat .setTimeZone (TimeZone .getTimeZone ("UTC" ));
86-
87- yearMonthDay = yearMonthDayFormat .format (date );
88- exactDate = exactDateFormat .format (date );
8949 }
9050
9151 /**
9252 * Constructs payload to be signed.
9353 *
94- * @return payload to sign
54+ * @return paylod to sign
9555 * @see <a href="https://cloud.google.com/storage/docs/access-control#Signed-URLs">Signed URLs</a>
9656 */
9757 public String constructUnsignedPayload () {
98- // TODO reverse order when V4 becomes default
99- if (Storage .SignUrlOption .SignatureVersion .V4 .equals (signatureVersion )) {
100- return constructV4UnsignedPayload ();
101- }
102- return constructV2UnsignedPayload ();
103- }
104-
105- private String constructV2UnsignedPayload () {
10658 StringBuilder payload = new StringBuilder ();
10759
10860 payload .append (httpVerb .name ()).append (COMPONENT_SEPARATOR );
@@ -115,72 +67,19 @@ private String constructV2UnsignedPayload() {
11567 payload .append (contentType );
11668 }
11769 payload .append (COMPONENT_SEPARATOR );
70+
11871 payload .append (expiration ).append (COMPONENT_SEPARATOR );
11972
12073 if (canonicalizedExtensionHeaders != null ) {
12174 payload .append (
122- new CanonicalExtensionHeadersSerializer (Storage .SignUrlOption .SignatureVersion .V2 )
123- .serialize (canonicalizedExtensionHeaders ));
75+ new CanonicalExtensionHeadersSerializer ().serialize (canonicalizedExtensionHeaders ));
12476 }
12577
12678 payload .append (canonicalizedResource );
12779
12880 return payload .toString ();
12981 }
13082
131- private String constructV4UnsignedPayload () {
132- StringBuilder payload = new StringBuilder ();
133-
134- payload .append (GOOG4_RSA_SHA256 ).append (COMPONENT_SEPARATOR );
135- payload .append (exactDate ).append (COMPONENT_SEPARATOR );
136- payload .append (yearMonthDay ).append (SCOPE ).append (COMPONENT_SEPARATOR );
137- payload .append (constructV4CanonicalRequestHash ());
138-
139- return payload .toString ();
140- }
141-
142- private String constructV4CanonicalRequestHash () {
143- StringBuilder canonicalRequest = new StringBuilder ();
144-
145- CanonicalExtensionHeadersSerializer serializer =
146- new CanonicalExtensionHeadersSerializer (Storage .SignUrlOption .SignatureVersion .V4 );
147-
148- canonicalRequest .append (httpVerb .name ()).append (COMPONENT_SEPARATOR );
149- canonicalRequest .append (canonicalizedResource ).append (COMPONENT_SEPARATOR );
150- canonicalRequest .append (constructV4QueryString ()).append (COMPONENT_SEPARATOR );
151- canonicalRequest
152- .append (serializer .serialize (canonicalizedExtensionHeaders ))
153- .append (COMPONENT_SEPARATOR );
154- canonicalRequest
155- .append (serializer .serializeHeaderNames (canonicalizedExtensionHeaders ))
156- .append (COMPONENT_SEPARATOR );
157- canonicalRequest .append ("UNSIGNED-PAYLOAD" );
158-
159- return Hashing .sha256 ()
160- .hashString (canonicalRequest .toString (), StandardCharsets .UTF_8 )
161- .toString ();
162- }
163-
164- public String constructV4QueryString () {
165- StringBuilder signedHeaders =
166- new CanonicalExtensionHeadersSerializer (Storage .SignUrlOption .SignatureVersion .V4 )
167- .serializeHeaderNames (canonicalizedExtensionHeaders );
168-
169- StringBuilder queryString = new StringBuilder ();
170- queryString .append ("X-Goog-Algorithm=" ).append (GOOG4_RSA_SHA256 ).append ("&" );
171- queryString .append (
172- "X-Goog-Credential="
173- + UrlEscapers .urlFormParameterEscaper ()
174- .escape (accountEmail + "/" + yearMonthDay + SCOPE )
175- + "&" );
176- queryString .append ("X-Goog-Date=" + exactDate + "&" );
177- queryString .append ("X-Goog-Expires=" + expiration + "&" );
178- queryString .append (
179- "X-Goog-SignedHeaders="
180- + UrlEscapers .urlFormParameterEscaper ().escape (signedHeaders .toString ()));
181- return queryString .toString ();
182- }
183-
18483 public HttpMethod getHttpVerb () {
18584 return httpVerb ;
18685 }
@@ -205,18 +104,6 @@ public URI getCanonicalizedResource() {
205104 return canonicalizedResource ;
206105 }
207106
208- public Storage .SignUrlOption .SignatureVersion getSignatureVersion () {
209- return signatureVersion ;
210- }
211-
212- public long getTimestamp () {
213- return timestamp ;
214- }
215-
216- public String getAccountEmail () {
217- return accountEmail ;
218- }
219-
220107 public static final class Builder {
221108
222109 private final HttpMethod httpVerb ;
@@ -225,9 +112,6 @@ public static final class Builder {
225112 private final long expiration ;
226113 private Map <String , String > canonicalizedExtensionHeaders ;
227114 private final URI canonicalizedResource ;
228- private Storage .SignUrlOption .SignatureVersion signatureVersion ;
229- private String accountEmail ;
230- private long timestamp ;
231115
232116 /**
233117 * Constructs builder.
@@ -250,9 +134,6 @@ public Builder(SignatureInfo signatureInfo) {
250134 this .expiration = signatureInfo .expiration ;
251135 this .canonicalizedExtensionHeaders = signatureInfo .canonicalizedExtensionHeaders ;
252136 this .canonicalizedResource = signatureInfo .canonicalizedResource ;
253- this .signatureVersion = signatureInfo .signatureVersion ;
254- this .accountEmail = signatureInfo .accountEmail ;
255- this .timestamp = signatureInfo .timestamp ;
256137 }
257138
258139 public Builder setContentMd5 (String contentMd5 ) {
@@ -274,41 +155,12 @@ public Builder setCanonicalizedExtensionHeaders(
274155 return this ;
275156 }
276157
277- public Builder setSignatureVersion (Storage .SignUrlOption .SignatureVersion signatureVersion ) {
278- this .signatureVersion = signatureVersion ;
279-
280- return this ;
281- }
282-
283- public Builder setAccountEmail (String accountEmail ) {
284- this .accountEmail = accountEmail ;
285-
286- return this ;
287- }
288-
289- public Builder setTimestamp (long timestamp ) {
290- this .timestamp = timestamp ;
291-
292- return this ;
293- }
294-
295158 /** Creates an {@code SignatureInfo} object from this builder. */
296159 public SignatureInfo build () {
297160 checkArgument (httpVerb != null , "Required HTTP method" );
298161 checkArgument (canonicalizedResource != null , "Required canonicalized resource" );
299162 checkArgument (expiration >= 0 , "Expiration must be greater than or equal to zero" );
300163
301- if (Storage .SignUrlOption .SignatureVersion .V4 .equals (signatureVersion )) {
302- checkArgument (accountEmail != null , "Account email required to use V4 signing" );
303- checkArgument (timestamp > 0 , "Timestamp required to use V4 signing" );
304- checkArgument (
305- expiration <= 604800 , "Expiration can't be longer than 7 days to use V4 signing" );
306- }
307-
308- if (canonicalizedExtensionHeaders == null ) {
309- canonicalizedExtensionHeaders = new HashMap <>();
310- }
311-
312164 return new SignatureInfo (this );
313165 }
314166 }
0 commit comments