in media_cdn/src/main/java/token/DualToken.java [93:210]
public static void signToken(
byte[] base64Key, String signatureAlgorithm, Optional<Instant> startTime,
Instant expirationTime, Optional<String> urlPrefix, Optional<String> fullPath,
Optional<String> pathGlobs, Optional<String> sessionId, Optional<String> data,
Optional<List<Header>> headers, Optional<String> ipRanges)
throws NoSuchAlgorithmException, InvalidKeyException {
String field = "";
byte[] decodedKey = Base64.getUrlDecoder().decode(base64Key);
// For most fields, the value in the token and the value to sign
// are the same. Compared to the token, the FullPath and Headers
// use a different string for the value to sign. To illustrate this difference,
// we'll keep the token and the value to be signed separate.
List<String> tokens = new ArrayList<>();
List<String> toSign = new ArrayList<>();
// Check for `fullPath` or `pathGlobs` or `urlPrefix`.
if (fullPath.isPresent()) {
tokens.add("FullPath");
toSign.add(String.format("FullPath=%s", fullPath.get()));
} else if (pathGlobs.isPresent()) {
field = String.format("PathGlobs=%s", pathGlobs.get().trim());
tokens.add(field);
toSign.add(field);
} else if (urlPrefix.isPresent()) {
field = String.format("URLPrefix=%s",
base64Encoder(urlPrefix.get().getBytes(StandardCharsets.UTF_8)));
tokens.add(field);
toSign.add(field);
} else {
throw new IllegalArgumentException(
"User Input Missing: One of `urlPrefix`, `fullPath` or `pathGlobs` must be specified");
}
// Check & parse optional params.
long epochDuration;
if (startTime.isPresent()) {
epochDuration = ChronoUnit.SECONDS.between(Instant.EPOCH, startTime.get());
field = String.format("Starts=%s", epochDuration);
tokens.add(field);
toSign.add(field);
}
if (expirationTime == null) {
expirationTime = Instant.now().plus(1, ChronoUnit.HOURS);
}
epochDuration = ChronoUnit.SECONDS.between(Instant.EPOCH, expirationTime);
field = String.format("Expires=%s", epochDuration);
tokens.add(field);
toSign.add(field);
if (sessionId.isPresent()) {
field = String.format("SessionID=%s", sessionId.get());
tokens.add(field);
toSign.add(field);
}
if (data.isPresent()) {
field = String.format("Data=%s", data.get());
tokens.add(field);
toSign.add(field);
}
if (headers.isPresent()) {
List<String> headerNames = new ArrayList<>();
List<String> headerPairs = new ArrayList<>();
for (Header entry : headers.get()) {
headerNames.add(entry.getName());
headerPairs.add(String.format("%s=%s", entry.getName(), entry.getValue()));
}
tokens.add(String.format("Headers=%s", String.join(",", headerNames)));
toSign.add(String.format("Headers=%s", String.join(",", headerPairs)));
}
if (ipRanges.isPresent()) {
field = String.format("IPRanges=%s",
base64Encoder(ipRanges.get().getBytes(StandardCharsets.US_ASCII)));
tokens.add(field);
toSign.add(field);
}
// Generate token.
String toSignJoined = String.join("~", toSign);
byte[] toSignBytes = toSignJoined.getBytes(StandardCharsets.UTF_8);
String algorithm = signatureAlgorithm.toLowerCase();
if (algorithm.equalsIgnoreCase("ed25519")) {
Ed25519PrivateKeyParameters privateKey = new Ed25519PrivateKeyParameters(decodedKey, 0);
Ed25519Signer signer = new Ed25519Signer();
signer.init(true, privateKey);
signer.update(toSignBytes, 0, toSignBytes.length);
byte[] signature = signer.generateSignature();
tokens.add(String.format("Signature=%s", base64Encoder(signature)));
} else if (algorithm.equalsIgnoreCase("sha256")) {
String sha256 = "HmacSHA256";
Mac mac = Mac.getInstance(sha256);
SecretKeySpec secretKeySpec = new SecretKeySpec(decodedKey, sha256);
mac.init(secretKeySpec);
byte[] signature = mac.doFinal(toSignBytes);
tokens.add(String.format("hmac=%s", Hex.toHexString(signature)));
} else if (algorithm.equalsIgnoreCase("sha1")) {
String sha1 = "HmacSHA1";
Mac mac = Mac.getInstance(sha1);
SecretKeySpec secretKeySpec = new SecretKeySpec(decodedKey, sha1);
mac.init(secretKeySpec);
byte[] signature = mac.doFinal(toSignBytes);
tokens.add(String.format("hmac=%s", Hex.toHexString(signature)));
} else {
throw new Error(
"Input Missing Error: `signatureAlgorithm` can only be one of `sha1`, `sha256` or "
+ "`ed25519`");
}
// The signed URL appended with the query parameters based on the
// specified URL prefix and configuration.
System.out.println(String.join("~", tokens));
}