<?php
# Part I: Keyed Caesar
# Example usage:
# encrypt('Hello cipher world!',array(1,19,6,4));
# decrypt('MMRIYUIYCPJLRCSLYQBRV',array(7,24,3));
# Note the these functions are not strictly inverses of each other,
# as the decryption function does not restore spaces or punctuation.
function encrypt($text, $key) {
# Turn text to uppercase
# Remove spaces and punctuation
# Turn text into an array
# Turn text into numbers, A=0, ...Z=25
foreach($text as $letter) {
$numbers[] = ord($letter) - 65; }
# Apply the key:
# For the nth letter of the plaintext, apply the nth key (modulo the key length)
# And hence shift the number that many places
foreach($numbers as $pos => $num) {
$shift = $key[$pos % count($key)]; $encnum[] = ($num + $shift) % 26;
}
# Turn the numbers back into letters
foreach($encnum as $num) {
}
}
function decrypt($enc, $key) {
# Turn encrypted text into an array
# Turn encrypted text into numbers, A=0, ...Z=25
foreach($enc as $letter) {
$encnum[] = ord($letter) - 65; }
# Apply the key in reverse:
# For the nth letter of the plaintext, apply the nth key (modulo the key length)
# And hence shift the number that many places in the negative direction
foreach($encnum as $pos => $num) {
$shift = $key[$pos % count($key)]; $numbers[] = (($num - $shift)+26) % 26;
}
# Turn the numbers back into letters
foreach($numbers as $num) {
$text[] = chr($num + 65); }
}
PD9waHAKCiMgUGFydCBJOiBLZXllZCBDYWVzYXIKIyBFeGFtcGxlIHVzYWdlOgojIGVuY3J5cHQoJ0hlbGxvIGNpcGhlciB3b3JsZCEnLGFycmF5KDEsMTksNiw0KSk7CiMgZGVjcnlwdCgnTU1SSVlVSVlDUEpMUkNTTFlRQlJWJyxhcnJheSg3LDI0LDMpKTsKIyBOb3RlIHRoZSB0aGVzZSBmdW5jdGlvbnMgYXJlIG5vdCBzdHJpY3RseSBpbnZlcnNlcyBvZiBlYWNoIG90aGVyLAojIGFzIHRoZSBkZWNyeXB0aW9uIGZ1bmN0aW9uIGRvZXMgbm90IHJlc3RvcmUgc3BhY2VzIG9yIHB1bmN0dWF0aW9uLgoKZnVuY3Rpb24gZW5jcnlwdCgkdGV4dCwgJGtleSkgewoJIyBUdXJuIHRleHQgdG8gdXBwZXJjYXNlCgkkdGV4dCA9IHN0cnRvdXBwZXIoJHRleHQpOwoJIyBSZW1vdmUgc3BhY2VzIGFuZCBwdW5jdHVhdGlvbgoJJHRleHQgPSBwcmVnX3JlcGxhY2UoJy9bXkEtWl0vJywnJywkdGV4dCk7CgkjIFR1cm4gdGV4dCBpbnRvIGFuIGFycmF5CgkkdGV4dCA9IHN0cl9zcGxpdCgkdGV4dCk7CgkjIFR1cm4gdGV4dCBpbnRvIG51bWJlcnMsIEE9MCwgLi4uWj0yNQoJJG51bWJlcnMgPSBhcnJheSgpOwoJZm9yZWFjaCgkdGV4dCBhcyAkbGV0dGVyKSB7CgkJJG51bWJlcnNbXSA9IG9yZCgkbGV0dGVyKSAtIDY1OwoJfQoJIyBBcHBseSB0aGUga2V5OgoJIyBGb3IgdGhlIG50aCBsZXR0ZXIgb2YgdGhlIHBsYWludGV4dCwgYXBwbHkgdGhlIG50aCBrZXkgKG1vZHVsbyB0aGUga2V5IGxlbmd0aCkKCSMgQW5kIGhlbmNlIHNoaWZ0IHRoZSBudW1iZXIgdGhhdCBtYW55IHBsYWNlcwoJJGVuY251bSA9IGFycmF5KCk7Cglmb3JlYWNoKCRudW1iZXJzIGFzICRwb3MgPT4gJG51bSkgewoJCSRzaGlmdCA9ICRrZXlbJHBvcyAlIGNvdW50KCRrZXkpXTsKCQkkZW5jbnVtW10gPSAoJG51bSArICRzaGlmdCkgJSAyNjsKCX0KCSMgVHVybiB0aGUgbnVtYmVycyBiYWNrIGludG8gbGV0dGVycwoJJGVuYyA9IGFycmF5KCk7Cglmb3JlYWNoKCRlbmNudW0gYXMgJG51bSkgewoJCSRlbmNbXSA9IGNocigkbnVtICsgNjUpOwoJfQoJCglyZXR1cm4gaW1wbG9kZSgnJywgJGVuYyk7Cn0KCmZ1bmN0aW9uIGRlY3J5cHQoJGVuYywgJGtleSkgewoJIyBUdXJuIGVuY3J5cHRlZCB0ZXh0IGludG8gYW4gYXJyYXkKCSRlbmMgPSBzdHJfc3BsaXQoJGVuYyk7CgkjIFR1cm4gZW5jcnlwdGVkIHRleHQgaW50byBudW1iZXJzLCBBPTAsIC4uLlo9MjUKCSRlbmNudW0gPSBhcnJheSgpOwoJZm9yZWFjaCgkZW5jIGFzICRsZXR0ZXIpIHsKCQkkZW5jbnVtW10gPSBvcmQoJGxldHRlcikgLSA2NTsKCX0KCSMgQXBwbHkgdGhlIGtleSBpbiByZXZlcnNlOgoJIyBGb3IgdGhlIG50aCBsZXR0ZXIgb2YgdGhlIHBsYWludGV4dCwgYXBwbHkgdGhlIG50aCBrZXkgKG1vZHVsbyB0aGUga2V5IGxlbmd0aCkKCSMgQW5kIGhlbmNlIHNoaWZ0IHRoZSBudW1iZXIgdGhhdCBtYW55IHBsYWNlcyBpbiB0aGUgbmVnYXRpdmUgZGlyZWN0aW9uCgkkbnVtYmVycyA9IGFycmF5KCk7Cglmb3JlYWNoKCRlbmNudW0gYXMgJHBvcyA9PiAkbnVtKSB7CgkJJHNoaWZ0ID0gJGtleVskcG9zICUgY291bnQoJGtleSldOwoJCSRudW1iZXJzW10gPSAoKCRudW0gLSAkc2hpZnQpKzI2KSAlIDI2OwoJfQoJIyBUdXJuIHRoZSBudW1iZXJzIGJhY2sgaW50byBsZXR0ZXJzCgkkdGV4dCA9IGFycmF5KCk7Cglmb3JlYWNoKCRudW1iZXJzIGFzICRudW0pIHsKCQkkdGV4dFtdID0gY2hyKCRudW0gKyA2NSk7Cgl9CgkKCXJldHVybiBpbXBsb2RlKCcnLCAkdGV4dCk7Cn0=