-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathSignedUrlDemo.java
101 lines (79 loc) · 3.51 KB
/
SignedUrlDemo.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package net.big2.gcshelper;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.StatusLine;
import org.apache.http.client.fluent.Request;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import static com.google.common.base.Preconditions.checkState;
public class SignedUrlDemo {
public static void main(String[] args) throws Exception {
// TODO: edit before run
String bucket = "test-bucket";
// TODO: edit before run
String filename = "/bob.txt";
// TODO: edit before run
String contentType = "text/plain";
// TODO: edit before run
byte[] data = "bob is here!".getBytes();
long expiration = System.currentTimeMillis() + 1000 * 5;
String signature = new Server().signString("PUT\n\n" + contentType + "\n" + expiration + "\n/" + bucket + filename);
new Uploader().uploadFile(bucket, filename, contentType, expiration, signature, data);
}
}
/**
* This is used to simulate "my application server" trying to sign a string that will be used as signature by the "uploader".
*/
class Server {
// TODO: edit before run
public static final String KEY_FILENAME = "my-privatekey.p12";
public static final String KEY_PASSWORD = "notasecret";
/**
* @param stringToSign As described in https://developers.google.com/storage/docs/accesscontrol#Signed-URLs
* @return Base64 encoded signature.
* @throws Exception
*/
public String signString(String stringToSign) throws Exception {
// load key
PrivateKey key = loadKeyFromPkcs12(KEY_FILENAME, KEY_PASSWORD.toCharArray());
// sign data
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initSign(key);
signer.update(stringToSign.getBytes("UTF-8"));
byte[] rawSignature = signer.sign();
return new String(Base64.encodeBase64(rawSignature, false), "UTF-8");
}
private static PrivateKey loadKeyFromPkcs12(String filename, char[] password) throws Exception {
FileInputStream fis = new FileInputStream(filename);
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(fis, password);
return (PrivateKey) ks.getKey("privatekey", password);
}
}
/**
* This is used to simulate unauthenticated user attempting to upload data to Google Cloud Storage using the signature
* generated by "my application server".
*/
class Uploader {
// TODO: edit before run
public static final String GOOGLE_ACCESS_ID = "[email protected]";
public String uploadFile(String bucket, String filename, String contentType, long expiration, String signature, byte[] data) throws IOException {
// construct URL
String url = "http://storage.googleapis.com/" + bucket + filename +
"?GoogleAccessId=" + GOOGLE_ACCESS_ID +
"&Expires=" + expiration +
"&Signature=" + URLEncoder.encode(signature, "UTF-8");
StatusLine statusLine = Request
// construct request method, header & data to upload
.Put(url)
.addHeader("Content-Type", contentType)
.bodyByteArray(data)
// send request to Google Cloud Storage
.execute().returnResponse().getStatusLine();
checkState(statusLine.getStatusCode() == 200, "Upload failed!");
return statusLine.toString();
}
}