function generateSecureRandomString($length, $elem = false) { // 文字列が0以下に指定されている場合は空文字を返す if ($length <= 0) { return ''; } // 使用文字が省略されている場合、小文字のアルファベットを使用してランダムな文字列を生成する if ($elem === false) { $elem = 'abcdefghijklmnopqrstuvwxyz'; } // 使用文字が1文字以上の記号を含む半角英数字で構成されているか正規表現でチェックする if (!preg_match('/\\a[\\x21-\\x7e]+\\z/', $elem)) { die('ランダム生成のための文字列に不正な文字が含まれています。'); } // 使用可能文字を1文字ずつ配列に格納する $chars = preg_split('//', $elem, -1, PREG_SPRIT_NO_EMPTY); // 「使用可能文字の配列」から重複文字を取り除く $chars = array_unique($chars); // 乱数のバイト文字数を取得する $bytes = getRandomBytes($length); if (strlen($bytes) <= 0) { echo 'パスワードの生成に失敗しました。<br>'; return ''; } // 「使用可能文字の配列」の添え字を乱数で指定して、ランダムな文字で1文字ずつ生成していく $str = ''; $charsLen = count($chars); for ($i = 0; $i < $length; $i++) { // バイト文字からASCII値を取得して剰余演算で配列の添え字を決定 $str .= $chars[ord($bytes[$i]) % $charsLen]; } return $str; }
function randomlyEncryptECBorCBC($data) { $key = getRandomBytes(16); $pad1 = getRandomBytes(rand(5, 10)); $pad2 = getRandomBytes(rand(5, 10)); if (rand(0, 1)) { return encryptAES128CBC("{$pad1}{$data}{$pad2}", $key, getRandomBytes(16)); } return encryptAES128ECB("{$pad1}{$data}{$pad2}", $key); }
*/ require_once '../utils/random-bytes.php'; require_once '10-implement-cbc-mode.php'; function getQuery($userData, $key, $iv) { $data = http_build_query(['comment1' => 'cooking MCs', 'userdata' => $userData, 'comment2' => ' lke a pound of bacon'], null, ';', PHP_QUERY_RFC3986); return encryptAES128CBC($data, $key, $iv); } function isAdmin($query, $key, $iv) { $data = decryptAES128CBC($query, $key, $iv); return strpos($data, ';admin=true;') !== false; } // don't output if we're included into another script. if (!debug_backtrace()) { $key = getRandomBytes(16); $iv = getRandomBytes(16); // 0..............f|0..............f|0..............f|0..............f|0..............f // comment1=cooking|%20MCs;userdata= // | |aaaaaaaaaaaaaaaa|bbbb;admin=true | // ;comment2=%20like%20a%20pound%20of%20bacon $badData = 'aaaaaaaaaaaaaaaabbbb;admin=true'; $goodData = 'aaaaaaaaaaaaaaaabbbbbbbbbbbbbbb'; $bitMask = substr($badData ^ $goodData, 16); $query = getQuery($goodData, $key, $iv); for ($i = 32; $i < 47; $i++) { $query[$i] = $query[$i] ^ $bitMask[$i - 32]; } print "Querystring has admin=true:\n"; print isAdmin($query, $key, $iv) ? "Yes\n\n" : "No :("; }
* * In this file find a similar set of Base64'd plaintext. Do with them exactly what you did with the first, but solve the problem differently. * * Instead of making spot guesses at to known plaintext, treat the collection of ciphertexts the same way you would repeating-key XOR. * * Obviously, CTR encryption appears different from repeated-key XOR, but with a fixed nonce they are effectively the same thing. * * To exploit this: take your collection of ciphertexts and truncate them to a common length (the length of the smallest ciphertext will work). * * Solve the resulting concatenation of ciphertexts as if for repeating- key XOR, with a key size of the length of the ciphertext you XOR'd. */ require_once '../utils/random-bytes.php'; require_once '../01-basics/06-break-repeating-key-xor.php'; require_once '18-implement-ctr-the-stream-cipher-mode.php'; $plaintexts = array_map('base64_decode', file('20-data.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)); $key = getRandomBytes(16); $ciphertexts = array_map('encryptAES128CTR', $plaintexts, array_fill(0, count($plaintexts), $key)); $cipherLens = array_map('strlen', $ciphertexts); // challenge text says use a common length, but we can recover more if we don't // this is because after transposition there's still enough data to statistically recover more /* $minLength = min($cipherLens); $truncated = array_map('str_split', $ciphertexts, array_fill(0, count($plaintexts), $minLength)); $truncated = array_column($truncated, 0); */ $truncated = $ciphertexts; // some copy/paste/tweak from challenge 6 print "\nSolving keys based on English Language scoring:\n"; $blocks = transposeBlocks($ciphertexts); $englishLanguageWeights['/'] = 0; list($topScores, $topChars) = scoreSingleByteXORStrings($blocks, $englishLanguageWeights, 20);
function __construct() { $this->key = getRandomBytes(64); }
function send($data) { $key = sha1($this->shared, true); $iv = getRandomBytes(16); $message = $iv . encryptAES128CBC($data, $key, $iv); print "{$this->name}: sending: {$data}\n"; $func = $this->onSend; $func($message); }
/** * Hash a password using BCRYPT algo and 8 iterations * @param string $password Clear password to be hashed * @return string Hashed password */ function hashPassword($password) { //Hash the clear password using bcrypt (8 iterations) $salt = '$2a$08$' . substr(strtr(base64_encode(getRandomBytes(16)), '+', '.'), 0, 22) . '$'; $hash = crypt($password, $salt); return $hash; }
function generatePassword($length) { return substr(preg_replace("/[^a-zA-Z0-9]/", "", base64_encode(getRandomBytes($length + 1))), 0, $length); }
function generatePassword() { // random length from 80 to 1000 $length = rand(80, 100); return substr(preg_replace("/[^a-zA-Z0-9]/", "", base64_encode(getRandomBytes($length + 1))), 0, $length); }
function encryptWithRandomPad($data, $seed = 0) { return encryptMT19937(getRandomBytes(rand(1, 20)) . $data, $seed); }
* * Food for thought. * A folkloric supposed benefit of CTR mode is the ability to easily "seek forward" into the ciphertext; to access byte N of the ciphertext, all you need to be able to do is generate byte N of the keystream. Imagine if you'd relied on that advice to, say, encrypt a disk. */ require_once '../utils/random-bytes.php'; require_once '../03-block-and-stream-crypto/18-implement-ctr-the-stream-cipher-mode.php'; function editAES128CTR($ciphertext, $key, $nonce = "", $offset, $newtext) { $newLen = strlen($newtext); // really dirty - I could calculate block specific keys, but I don't really have to for this. $plaintext = encryptAES128CTR($ciphertext, $key, $nonce); $plainLen = strlen($plaintext); $newPlaintext = ''; if ($offset > 0) { $newPlaintext = substr($plaintext, 0, $offset); } $newPlaintext .= $newtext; if ($newLen + $offset < $plainLen) { $newPlaintext .= substr($plaintext, $newLen + $offset); } return encryptAES128CTR($newPlaintext, $key, $nonce); } // don't output if we're included into another script. if (!debug_backtrace()) { $key = getRandomBytes(16); $nonce = getRandomBytes(16); $ciphertext = encryptAES128CTR(decryptAES128ECB(base64_decode(file_get_contents('25-data.txt')), 'YELLOW SUBMARINE'), $key, $nonce); $editedCiphertext = editAES128CTR($ciphertext, $key, $nonce, 0, str_repeat("", strlen($ciphertext))); print "Recovered plaintext:\n"; print $ciphertext ^ $editedCiphertext . "\n\n"; }
function send($data) { $obj = new \stdClass(); $obj->msg = 'dat'; $obj->data = $data; $data = json_encode($obj); if (!is_null($this->shared)) { $key = sha1($this->shared, true); $iv = getRandomBytes(16); $data = $iv . encryptAES128CBC($data, $key, $iv); } $dataLen = strlen($data); print "{$this->name}: sending {$dataLen} bytes\n"; $func = $this->onSend; $func($data); }
foreach ($_POST['events'] as $event) { $eventStuff = explode(", ", $event); insertNewEvent($eventStuff[0], $eventStuff[1], $eventStuff[2], $eventStuff[3], $clubid, 1, $conn); } //Now we need to notify the faculty member that they need to approve a club //1. Get Faculty Email String! $emailRes = $conn->query("SELECT username, id FROM sgstudents.seniors_data WHERE last_name = '{$advisor[1]}' AND (preferred_name = '{$advisor[0]}' OR first_name = '{$advisor['0']}')"); $facultyUsername = $emailRes->fetch_assoc(); $facultyId = $facultyUsername['id']; $facultyEmail = $facultyUsername['username'] . '@taftschool.org'; $emailString = "Hello!\r\n\tYou have been requested as a club advisor for the {$name}!\r\nWhose mission statement is: {$mission_statement}"; $emailString .= "\r\nAnd led by student leaders: {$_POST['leaders'][0]}"; $emailString .= "\r\nLink to Live Club Page: http://" . $_SERVER['SERVER_NAME'] . "/clubs/club.php?clubId=" . $clubid; $emailString .= "\r\nClick this link within 24 hours to accept this invitation: "; //2. Generate One-Way Hash with Salt $salt = getRandomBytes(32); $saltyString = $name . $salt . $advisor[0] . $salt . $mission_statement . $salt; $md5HashedString = md5($saltyString) . substr(md5($salt . $facultyId), 0, 8); //24 bytes $salt = $saltyString = ""; $md5HashedString = substr($md5HashedString, 0, 24); //10^28 total possibilities for hash, we should be safe in assuming no collisions //3. Put Hash Into Database: $conn->query("INSERT INTO taftclubs.faculty_approval_links (hash, clubId, dateIssued)\n VALUES('{$md5HashedString}', {$clubid}, NOW())"); error_log($conn->error); //4. Append Hash URL onto Email String $emailString .= "http://" . $_SERVER['SERVER_NAME'] . "/clubs/scripts/approve.php?hash=" . $md5HashedString; sendMail(array($facultyEmail), "Club Advisor Request", $emailString, "From: TaftClubs <*****@*****.**>", $conn); error_log($conn->error); } }