Last active
April 9, 2018 16:53
-
-
Save pascalduez/c72df9e25fc8866376d5 to your computer and use it in GitHub Desktop.
Vigenère cipher in Sass.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ---- | |
// Sass (v3.3.8) | |
// Compass (v1.0.0.alpha.19) | |
// ---- | |
// Vigenère cipher. | |
// https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher | |
// Get char code from `$str` at `$index` in range [1-52][A-Za-z]. | |
// –––––––– | |
// @param [string] $str | |
// @param [number] $index | |
// –––––––– | |
// @return [number] | |
@function char-code-at($str, $index: 1) { | |
$chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; | |
@return str-index($chars, str-slice($str, $index, $index)); | |
} | |
// Get char at `$index` in range [1-52][A-Za-z]. | |
// –––––––– | |
// @param [number] $index | |
// –––––––– | |
// @return [string] | |
@function from-char-code($index) { | |
$chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; | |
@return str-slice($chars, $index, $index); | |
} | |
// Filter and build the numeric key in range [0-25]. | |
// –––––––– | |
// @param [string] $key | |
// –––––––– | |
// @return [list] | |
@function key($key) { | |
$result: (); | |
@for $i from 1 through str-length($key) { | |
$c: char-code-at($key, $i); | |
@if $c { | |
$result: append($result, ($c - 1) % 26); | |
} | |
} | |
@return $result; | |
} | |
// Encrypt a `$message` with the vigenère cipher based on `$key`. | |
// –––––––– | |
// @param [string] $message | |
// @param [string] $key | |
// –––––––– | |
// @return [string] | |
@function vigenere-encrypt($message, $key) { | |
@return vigenere($message, key($key)); | |
} | |
// Decrypt a vigenère encrypted `$message` based on `$key`. | |
// –––––––– | |
// @param [string] $message | |
// @param [string] $key | |
// –––––––– | |
// @return [string] | |
@function vigenere-decrypt($message, $key) { | |
$key: key($key); | |
@for $i from 1 through length($key) { | |
$key: set-nth($key, $i, (26 - nth($key, $i) % 26)); | |
} | |
@return vigenere($message, $key); | |
} | |
// Vigenère cipher encoder/decoder. | |
// –––––––– | |
// @param [string] $message | |
// @param [string] $key | |
// –––––––– | |
// @return [string] | |
@function vigenere($message, $key) { | |
$length: length($key); | |
$result: ''; | |
$j: 1; | |
@for $i from 1 through str-length($message) { | |
$col: char-code-at($message, $i); | |
$match: ''; | |
@if $col { | |
// Uppercase $col <= 26 | |
// Lowercase $col > 26 | |
$pos: if($col > 26, 27, 1); | |
$match: (($col - $pos) + nth($key, (($j - 1) % $length + 1))) % 26 + $pos; | |
$match: from-char-code($match); | |
$j: $j + 1; | |
} | |
@else { | |
// Non [A-Za-z] char. | |
$match: str-slice($message, $i, $i); | |
} | |
$result: $result + $match; | |
} | |
@return $result; | |
} | |
// Tests | |
vigenere { | |
$fixture: ( | |
('attackatdown', 'lemon', 'lxfopvefrbhr'), | |
('Helmholtzplatz', 'Berlin', 'Iicxpbmxqatnud'), | |
('Hey! how’s it going ?', 'Amiens', 'Hqg! lbo’s ub kbans ?'), | |
('Les sanglots longs Des violons Blessent mon cœur D’une langueur Monotone.', 'BBC', 'Mfu tbphmqut npoit Egt wkpmqot Dmfutfpu nqo dœws E’wof nboivfws Nqopvpog.'), | |
('Punkt, Punkt, Komma, Strich, fertig ist das Mondgesicht.', 'Saßy', 'Hulct, Nmnil, Kmemy, Ktpacf, xeplie asr vaq Eolvgckiazt.') | |
); | |
/* Encrypt */ | |
$tests: ''; | |
@each $test in $fixture { | |
$pass: vigenere-encrypt(nth($test, 1), nth($test, 2)) == nth($test, 3); | |
$tests: $tests + if($pass, '✔ ', 'X '); | |
} | |
tests: $tests; | |
/* Decrypt */ | |
$tests: ''; | |
@each $test in $fixture { | |
$pass: vigenere-decrypt(nth($test, 3), nth($test, 2)) == nth($test, 1); | |
$tests: $tests + if($pass, '✔ ', 'X '); | |
} | |
tests: $tests; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@charset "UTF-8"; | |
vigenere { | |
/* Encrypt */ | |
tests: "✔ ✔ ✔ ✔ ✔ "; | |
/* Decrypt */ | |
tests: "✔ ✔ ✔ ✔ ✔ "; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment