<?php
# Part II: Hardened Keyed Caesar
# Example usage:
# encrypt('Ciphers are hard!',array(1,2,3,4),3);
# decrypt('GQBXULQCTKROFV',array(1,2,3,4),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, $inc) {
# 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)]; # Add the incerement times the position (starting at 1)
$shift += (($pos + 1) * $inc) % 26;
$encnum[] = ($num + $shift) % 26;
}
# Turn the numbers back into letters
foreach($encnum as $num) {
}
}
function decrypt($enc, $key, $inc) {
# 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)]; # Add the incerement times the position (starting at 1)
$shift += (($pos + 1) * $inc) % 26;
$numbers[] = (($num - $shift)+52) % 26;
}
# Turn the numbers back into letters
foreach($numbers as $num) {
$text[] = chr($num + 65); }
}
PD9waHAKCiMgUGFydCBJSTogSGFyZGVuZWQgS2V5ZWQgQ2Flc2FyCiMgRXhhbXBsZSB1c2FnZToKIyBlbmNyeXB0KCdDaXBoZXJzIGFyZSBoYXJkIScsYXJyYXkoMSwyLDMsNCksMyk7CiMgZGVjcnlwdCgnR1FCWFVMUUNUS1JPRlYnLGFycmF5KDEsMiwzLDQpLDMpOwojIE5vdGUgdGhlIHRoZXNlIGZ1bmN0aW9ucyBhcmUgbm90IHN0cmljdGx5IGludmVyc2VzIG9mIGVhY2ggb3RoZXIsCiMgYXMgdGhlIGRlY3J5cHRpb24gZnVuY3Rpb24gZG9lcyBub3QgcmVzdG9yZSBzcGFjZXMgb3IgcHVuY3R1YXRpb24uCgpmdW5jdGlvbiBlbmNyeXB0KCR0ZXh0LCAka2V5LCAkaW5jKSB7CgkjIFR1cm4gdGV4dCB0byB1cHBlcmNhc2UKCSR0ZXh0ID0gc3RydG91cHBlcigkdGV4dCk7CgkjIFJlbW92ZSBzcGFjZXMgYW5kIHB1bmN0dWF0aW9uCgkkdGV4dCA9IHByZWdfcmVwbGFjZSgnL1teQS1aXS8nLCcnLCR0ZXh0KTsKCSMgVHVybiB0ZXh0IGludG8gYW4gYXJyYXkKCSR0ZXh0ID0gc3RyX3NwbGl0KCR0ZXh0KTsKCSMgVHVybiB0ZXh0IGludG8gbnVtYmVycywgQT0wLCAuLi5aPTI1CgkkbnVtYmVycyA9IGFycmF5KCk7Cglmb3JlYWNoKCR0ZXh0IGFzICRsZXR0ZXIpIHsKCQkkbnVtYmVyc1tdID0gb3JkKCRsZXR0ZXIpIC0gNjU7Cgl9CgkjIEFwcGx5IHRoZSBrZXk6CgkjIEZvciB0aGUgbnRoIGxldHRlciBvZiB0aGUgcGxhaW50ZXh0LCBhcHBseSB0aGUgbnRoIGtleSAobW9kdWxvIHRoZSBrZXkgbGVuZ3RoKQoJIyBBbmQgaGVuY2Ugc2hpZnQgdGhlIG51bWJlciB0aGF0IG1hbnkgcGxhY2VzCgkkZW5jbnVtID0gYXJyYXkoKTsKCWZvcmVhY2goJG51bWJlcnMgYXMgJHBvcyA9PiAkbnVtKSB7CgkJJHNoaWZ0ID0gJGtleVskcG9zICUgY291bnQoJGtleSldOwoJCSMgQWRkIHRoZSBpbmNlcmVtZW50IHRpbWVzIHRoZSBwb3NpdGlvbiAoc3RhcnRpbmcgYXQgMSkgCgkJJHNoaWZ0ICs9ICgoJHBvcyArIDEpICogJGluYykgJSAyNjsKCQkkZW5jbnVtW10gPSAoJG51bSArICRzaGlmdCkgJSAyNjsKCX0KCSMgVHVybiB0aGUgbnVtYmVycyBiYWNrIGludG8gbGV0dGVycwoJJGVuYyA9IGFycmF5KCk7Cglmb3JlYWNoKCRlbmNudW0gYXMgJG51bSkgewoJCSRlbmNbXSA9IGNocigkbnVtICsgNjUpOwoJfQoJCglyZXR1cm4gaW1wbG9kZSgnJywgJGVuYyk7Cn0KCmZ1bmN0aW9uIGRlY3J5cHQoJGVuYywgJGtleSwgJGluYykgewoJIyBUdXJuIGVuY3J5cHRlZCB0ZXh0IGludG8gYW4gYXJyYXkKCSRlbmMgPSBzdHJfc3BsaXQoJGVuYyk7CgkjIFR1cm4gZW5jcnlwdGVkIHRleHQgaW50byBudW1iZXJzLCBBPTAsIC4uLlo9MjUKCSRlbmNudW0gPSBhcnJheSgpOwoJZm9yZWFjaCgkZW5jIGFzICRsZXR0ZXIpIHsKCQkkZW5jbnVtW10gPSBvcmQoJGxldHRlcikgLSA2NTsKCX0KCSMgQXBwbHkgdGhlIGtleSBpbiByZXZlcnNlOgoJIyBGb3IgdGhlIG50aCBsZXR0ZXIgb2YgdGhlIHBsYWludGV4dCwgYXBwbHkgdGhlIG50aCBrZXkgKG1vZHVsbyB0aGUga2V5IGxlbmd0aCkKCSMgQW5kIGhlbmNlIHNoaWZ0IHRoZSBudW1iZXIgdGhhdCBtYW55IHBsYWNlcyBpbiB0aGUgbmVnYXRpdmUgZGlyZWN0aW9uCgkkbnVtYmVycyA9IGFycmF5KCk7Cglmb3JlYWNoKCRlbmNudW0gYXMgJHBvcyA9PiAkbnVtKSB7CgkJJHNoaWZ0ID0gJGtleVskcG9zICUgY291bnQoJGtleSldOwoJCSMgQWRkIHRoZSBpbmNlcmVtZW50IHRpbWVzIHRoZSBwb3NpdGlvbiAoc3RhcnRpbmcgYXQgMSkKCQkkc2hpZnQgKz0gKCgkcG9zICsgMSkgKiAkaW5jKSAlIDI2OwoJCSRudW1iZXJzW10gPSAoKCRudW0gLSAkc2hpZnQpKzUyKSAlIDI2OwoJfQoJIyBUdXJuIHRoZSBudW1iZXJzIGJhY2sgaW50byBsZXR0ZXJzCgkkdGV4dCA9IGFycmF5KCk7Cglmb3JlYWNoKCRudW1iZXJzIGFzICRudW0pIHsKCQkkdGV4dFtdID0gY2hyKCRudW0gKyA2NSk7Cgl9CgkKCXJldHVybiBpbXBsb2RlKCcnLCAkdGV4dCk7Cn0=