Skip to content

Commit 54bc2c1

Browse files
authored
fix: add case insensitive check for X-Goog-Content-SHA256 in SignatureInfo (googleapis#3337)
1 parent 73f263f commit 54bc2c1

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

google-cloud-storage/src/main/java/com/google/cloud/storage/SignatureInfo.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,13 @@ private String constructV4CanonicalRequestHash() {
170170
.append(serializer.serializeHeaderNames(canonicalizedExtensionHeaders))
171171
.append(COMPONENT_SEPARATOR);
172172

173-
String userProvidedHash = canonicalizedExtensionHeaders.get("X-Goog-Content-SHA256");
173+
String userProvidedHash = null;
174+
for (Map.Entry<String, String> entry : canonicalizedExtensionHeaders.entrySet()) {
175+
if ("X-Goog-Content-SHA256".equalsIgnoreCase(entry.getKey())) {
176+
userProvidedHash = entry.getValue();
177+
break;
178+
}
179+
}
174180
canonicalRequest.append(userProvidedHash == null ? "UNSIGNED-PAYLOAD" : userProvidedHash);
175181

176182
return Hashing.sha256()

google-cloud-storage/src/test/java/com/google/cloud/storage/SignatureInfoTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
import static org.junit.Assert.assertTrue;
2121

2222
import com.google.cloud.storage.SignatureInfo.Builder;
23+
import com.google.common.hash.Hashing;
2324
import java.net.URI;
25+
import java.nio.charset.StandardCharsets;
2426
import java.util.HashMap;
2527
import java.util.Map;
2628
import org.junit.Test;
@@ -98,4 +100,39 @@ public void constructV4QueryString() {
98100
+ "auto%2Fstorage%2Fgoog4_request&X-Goog-Date=20010909T014640Z&X-Goog-Expires=10&X-Goog-SignedHeaders=host",
99101
queryString);
100102
}
103+
104+
@Test
105+
public void constructV4UnsignedPayloadWithContentSha256Header() {
106+
Builder builder = new SignatureInfo.Builder(HttpMethod.PUT, 10L, URI.create(RESOURCE));
107+
builder.setSignatureVersion(Storage.SignUrlOption.SignatureVersion.V4);
108+
builder.setAccountEmail("[email protected]");
109+
builder.setTimestamp(1000000000000L);
110+
111+
Map<String, String> extensionHeaders = new HashMap<>();
112+
// Add the header with a lowercase key, which triggers the bug.
113+
String contentSha256 = "sha256";
114+
extensionHeaders.put("X-goog-content-sha256", contentSha256);
115+
builder.setCanonicalizedExtensionHeaders(extensionHeaders);
116+
117+
// This is the payload hash that SHOULD be generated
118+
String correctCanonicalRequest =
119+
"PUT\n"
120+
+ "/bucketName/blobName\n"
121+
+ "X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=me%40google.com%2F20010909%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20010909T014640Z&X-Goog-Expires=10&X-Goog-SignedHeaders=host%3Bx-goog-content-sha256\n"
122+
+ "host:storage.googleapis.com\n"
123+
+ "x-goog-content-sha256:"
124+
+ contentSha256
125+
+ "\n"
126+
+ "\n"
127+
+ "host;x-goog-content-sha256\n"
128+
+ contentSha256;
129+
String expectedPayloadHash =
130+
Hashing.sha256().hashString(correctCanonicalRequest, StandardCharsets.UTF_8).toString();
131+
132+
String unsignedPayload = builder.build().constructUnsignedPayload();
133+
String[] parts = unsignedPayload.split("\n");
134+
String generatedPayloadHash = parts[parts.length - 1];
135+
136+
assertEquals(expectedPayloadHash, generatedPayloadHash);
137+
}
101138
}

0 commit comments

Comments
 (0)