!!!Listing 1: Serverseitige Token-Validierung (PHP) $salt = array(2, 5, 71, 83, 8, 3, 1); $saltStr = vsprintf(str_repeat('%c', count($salt)), $salt); $iv = array(5, 32, 91, 24, 7, 114, 2, 30, 5, 66, 1, 8, 21, 4, 9, 48); $ivStr = vsprintf(str_repeat('%c', count($iv)), $iv); $encryptionCode = "***********"; function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false) { $algorithm = strtolower($algorithm); $hash_length = strlen(hash($algorithm, "", true)); $block_count = ceil($key_length / $hash_length); $output = ""; for($i = 1; $i <= $block_count; $i++) { $last = $salt . pack("N", $i); $last = $xorsum = hash_hmac($algorithm, $last, $password, true); for ($j = 1; $j < $count; $j++) { $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true)); } $output .= $xorsum; } if($raw_output) return substr($output, 0, $key_length); else return bin2hex(substr($output, 0, $key_length)); } function validateToken() { global $saltStr; global $encryptionCode; global $ivStr; if (array_key_exists("t", $_GET) && array_key_exists("h", $_GET)) { $timestamp = $_GET["t"]; $hash = $_GET["h"]; if ($timestamp != null && $hash != null) { $diff = time() - intval($timestamp); if ($diff > 120) { return false; } $requestUri = $_SERVER['REQUEST_URI']; $requestUriParts = parse_url($requestUri); $requestUriPath = $requestUriParts["path"]; $keys = array(); foreach ($_GET as $key => $value) { if ($key != "h") { array_push($keys, $key); } } rsort($keys, SORT_STRING); $strToSign = $requestUriPath . "?"; for ($i = sizeof($keys) - 1; $i >= 0; $i--) { $key = $keys[$i]; $strToSign .= $key . "=" . $_GET[$key]; if ($i > 0) { $strToSign .= "&"; } } $hashedPassword = pbkdf2("sha1", $encryptionCode, $saltStr, 1024, 256); $hashedPassword = pack("H*", $hashedPassword); $signature = bin2hex(openssl_encrypt($strToSign, "aes-256-cbc", $hashedPassword, true, $ivStr)); return $hash == $signature; } else { return false; } } !!!Listing 2: Tokengenerierung mit Forge var KEY_LENGTH = 32; var ENCRYPTION_CODE = "***********"; var salt = [2, 5, 71, 83, 8, 3, 1 ]; saltHexStr = salt.map(function(v) { var str = v.toString(16); return str.length == 1 ? "0" + str : str; }).join(""); var saltBytes = forge.util.hexToBytes(saltHexStr); var iv = [5, 32, 91, 24, 7, 114, 2, 30, 5, 66, 1, 8, 21, 4, 9, 48 ]; var ivHexStr = iv.map(function(v) { var str = v.toString(16); return str.length == 1 ? "0" + str : str; }).join(""); var ivBytes = forge.util.hexToBytes(ivHexStr); var date = new Date(); var currentTime = Math.floor(date.getTime() / 1000); var key = forge.pkcs5.pbkdf2(ENCRYPTION_CODE, saltBytes, 1024, KEY_LENGTH); var dkHex = forge.util.bytesToHex(key); var plainURLToBeEncrypted = '/getdata.json?' + params + '&t=' + currentTime; var input = forge.util.createBuffer(plainURLToBeEncrypted); var cipher = forge.cipher.createCipher('AES-CBC', key); cipher.start({ iv : ivBytes }); cipher.update(input); var status = cipher.finish(); var ciphertext = cipher.output.data; var ciphertextHexStr = forge.util.bytesToHex(ciphertext); return "http://myService.com/getdata.json?t=" + currentTime + "&h=" + ciphertextHexStr + "&" + params; !!!Listing 3: Beispiel-Java-Implementierung byte[] SALT = {2, 5, 71, 83, 8, 3, 1 }; IvParameterSpec INITIALIZATION_VECTOR = new IvParameterSpec(new byte[] { 5, 32, 91, 24, 7, 114, 2, 30, 5, 66, 1, 8, 21, 4, 9, 48 }); String encryptionCode = "***********"; SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); PBEKeySpec pbeKeySpec = new PBEKeySpec(encryptionCode.toCharArray(), SALT, 1024, 256); SecretKey tmp = secretKeyFactory.generateSecret(pbeKeySpec); SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey, INITIALIZATION_VECTOR); byte[] cipherText = cipher.doFinal(plain.toString().getBytes("UTF-8")); return Hex.byteToHex(cipherText);