Skip to content

Commit d686ce5

Browse files
committed
Added crc32 checksuming support
1 parent 3c15ef2 commit d686ce5

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import com.google.cloud.storage.multipartupload.model.CreateMultipartUploadResponse;
3131
import com.google.cloud.storage.multipartupload.model.UploadPartRequest;
3232
import com.google.cloud.storage.multipartupload.model.UploadPartResponse;
33+
import com.google.common.hash.HashCode;
34+
import com.google.common.hash.Hashing;
3335
import java.io.IOException;
3436
import java.io.InputStream;
3537
import java.io.OutputStream;
@@ -38,6 +40,7 @@
3840
import java.net.URI;
3941
import java.net.URL;
4042
import java.net.URLEncoder;
43+
import java.nio.ByteBuffer;
4144
import java.nio.charset.StandardCharsets;
4245
import java.security.MessageDigest;
4346
import java.security.NoSuchAlgorithmException;
@@ -134,11 +137,17 @@ public CompleteMultipartUploadResponse completeMultipartUpload(CompleteMultipart
134137

135138
MessageDigest md = MessageDigest.getInstance("MD5");
136139
String contentMd5 = Base64.getEncoder().encodeToString(md.digest(xmlBodyBytes));
140+
141+
HashCode crc32cHash = Hashing.crc32c().hashBytes(xmlBodyBytes);
142+
byte[] crc32cBytes = ByteBuffer.allocate(4).putInt(crc32cHash.asInt()).array();
143+
String crc32cBase64 = Base64.getEncoder().encodeToString(crc32cBytes);
144+
137145
String date = getRfc1123Date();
138146
String contentType = "application/xml";
147+
String canonicalizedHeaders = "x-goog-hash:crc32c=" + crc32cBase64 + "\n";
139148

140149
// GCS Signature Rule #3: The query string IS NOT included for the POST complete request.
141-
String signature = signRequest("POST", contentMd5, contentType, date, resourcePath, GOOGLE_SECRET_KEY);
150+
String signature = signRequest("POST", contentMd5, contentType, date, canonicalizedHeaders, resourcePath, GOOGLE_SECRET_KEY);
142151
String authHeader = "GOOG1 " + GOOGLE_ACCESS_KEY + ":" + signature;
143152

144153
HttpURLConnection connection = (HttpURLConnection) new URL(uri).openConnection();
@@ -147,6 +156,7 @@ public CompleteMultipartUploadResponse completeMultipartUpload(CompleteMultipart
147156
connection.setRequestProperty("Authorization", authHeader);
148157
connection.setRequestProperty("Content-Type", contentType);
149158
connection.setRequestProperty("Content-MD5", contentMd5);
159+
connection.setRequestProperty("x-goog-hash", "crc32c=" + crc32cBase64);
150160
connection.setFixedLengthStreamingMode(xmlBodyBytes.length);
151161
connection.setDoOutput(true);
152162

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,12 @@ public static String readStream(InputStream inputStream) throws IOException {
4343
}
4444

4545
public static String signRequest(String httpVerb, String contentMd5, String contentType, String date, String canonicalizedResource, String googleSecretKey) {
46+
return signRequest(httpVerb, contentMd5, contentType, date, "", canonicalizedResource, googleSecretKey);
47+
}
48+
49+
public static String signRequest(String httpVerb, String contentMd5, String contentType, String date, String canonicalizedHeaders, String canonicalizedResource, String googleSecretKey) {
4650
try {
47-
String stringToSign = httpVerb + "\n" + contentMd5 + "\n" + contentType + "\n" + date + "\n" + canonicalizedResource;
51+
String stringToSign = httpVerb + "\n" + contentMd5 + "\n" + contentType + "\n" + date + "\n" + canonicalizedHeaders + canonicalizedResource;
4852
Mac sha1Hmac = Mac.getInstance("HmacSHA1");
4953
SecretKeySpec secretKey = new SecretKeySpec(googleSecretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
5054
sha1Hmac.init(secretKey);

0 commit comments

Comments
 (0)