Basic cryptographic ciphers and utilities.

Redefined classes

redef class Bytes

crypto :: basic_ciphers $ Bytes

A buffer containing Byte-manipulation facilities
redef enum Char

crypto :: basic_ciphers $ Char

Native characters.
redef enum Int

crypto :: basic_ciphers $ Int

Native integer numbers.
redef abstract class Text

crypto :: basic_ciphers $ Text

High-level abstraction for all text representations

All class definitions

redef class Bytes

crypto :: basic_ciphers $ Bytes

A buffer containing Byte-manipulation facilities
redef enum Char

crypto :: basic_ciphers $ Char

Native characters.
redef enum Int

crypto :: basic_ciphers $ Int

Native integer numbers.
redef abstract class Text

crypto :: basic_ciphers $ Text

High-level abstraction for all text representations
package_diagram crypto::basic_ciphers basic_ciphers core core crypto::basic_ciphers->core crypto::crypto crypto crypto::crypto->crypto::basic_ciphers crapto::xor xor crapto::xor->crypto::crypto websocket::websocket websocket websocket::websocket->crypto::crypto crapto::xor... ... crapto::xor...->crapto::xor websocket::websocket... ... websocket::websocket...->websocket::websocket

Ancestors

module abstract_collection

core :: abstract_collection

Abstract collection classes and services.
module abstract_text

core :: abstract_text

Abstract class for manipulation of sequences of characters
module array

core :: array

This module introduces the standard array structure.
module bitset

core :: bitset

Services to handle BitSet
module bytes

core :: bytes

Services for byte streams and arrays
module circular_array

core :: circular_array

Efficient data structure to access both end of the sequence.
module codec_base

core :: codec_base

Base for codecs to use with streams
module codecs

core :: codecs

Group module for all codec-related manipulations
module collection

core :: collection

This module define several collection classes.
module environ

core :: environ

Access to the environment variables of the process
module error

core :: error

Standard error-management infrastructure.
module exec

core :: exec

Invocation and management of operating system sub-processes.
module file

core :: file

File manipulations (create, read, write, etc.)
module fixed_ints

core :: fixed_ints

Basic integers of fixed-precision
module fixed_ints_text

core :: fixed_ints_text

Text services to complement fixed_ints
module flat

core :: flat

All the array-based text representations
module gc

core :: gc

Access to the Nit internal garbage collection mechanism
module hash_collection

core :: hash_collection

Introduce HashMap and HashSet.
module iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module kernel

core :: kernel

Most basic classes and methods.
module list

core :: list

This module handle double linked lists
module math

core :: math

Mathematical operations
module native

core :: native

Native structures for text and bytes
module numeric

core :: numeric

Advanced services for Numeric types
module protocol

core :: protocol

module queue

core :: queue

Queuing data structures and wrappers
module range

core :: range

Module for range of discrete objects.
module re

core :: re

Regular expression support for all services based on Pattern
module ropes

core :: ropes

Tree-based representation of a String.
module sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
module stream

core :: stream

Input and output streams of characters
module text

core :: text

All the classes and methods related to the manipulation of text entities
module time

core :: time

Management of time and dates
module union_find

core :: union_find

union–find algorithm using an efficient disjoint-set data structure
module utf8

core :: utf8

Codec for UTF-8 I/O

Parents

module core

core :: core

Standard classes and methods used by default by Nit programs and libraries.

Children

module crypto

crypto :: crypto

Mix of all things cryptography-related

Descendants

module a_star-m

a_star-m

module crapto

crapto :: crapto

Cryptographic attacks and utilities.
module websocket

websocket :: websocket

Adds support for a websocket connection in Nit
module websocket_server

websocket :: websocket_server

Sample module for a minimal chat server using Websockets on port 8088
module xor

crapto :: xor

Cryptographic attacks and utilities for XOR-based algorithms.
# Basic cryptographic ciphers and utilities.
module basic_ciphers

redef class Char
	# Rotates self of `x`
	#
	# NOTE: works on letters only
	#
	#     assert 'x'.rot(6) == 'd'
	#     assert 'T'.rot(15) == 'I'
	#     assert '1'.rot(10) == '1'
	#     assert '$'.rot(10) == '$'
	#     assert 'z'.rot(-2) == 'x'
	fun rot(x: Int): Char do
		if not is_letter then return self
		x = x % 26
		if x < 0 then x += 26
		var up = false
		var val = code_point
		if is_upper then
			up = true
			val += 32
		end
		val += x
		if val > 122 then val -= 26
		if up then val -= 32
		return val.code_point
	end
end

redef class Text
	# Performs a Rotation of `x` on each letter of self
	#
	# Works by replacing every character in `self` by its
	# rotated char.
	#
	# Say we have a rotation of `3` (Caesar rotation, for
	# culture) for a string : "aybabtu"
	#
	# a, rotated by 3 becomes d
	# y, rotated by 3 becomes b
	# b, rotated by 3 becomes e
	# t, rotated by 3 becomes w
	# u, rotated by 3 becomes x
	#
	# We then replace every letter in our original string by
	# their rotated representations, therefore yielding : "dbedewx"
	#
	#     assert "All your base are belong to us".rot(13) == "Nyy lbhe onfr ner orybat gb hf"
	#     assert "This is no moon.".rot(4).rot(22) == "This is no moon."
	#
	# NOTE : Works on letters only
	# NOTE : This cipher is symmetrically decrypted with an `x` of 26-`x`
	fun rot(x: Int): Text do
		var rot = x % 26
		if rot < 0 then rot += 26
		var d = new FlatBuffer.with_capacity(length)
		for i in chars do
			d.add i.rot(rot)
		end
		return d.to_s
	end

	# Returns a rail-fence cipher from `self` with `depth` rails
	#
	# Rail works by drawing a zig-zag pattern on `depth` rails.
	#
	# Say we have "fuckingbehemoth".railfence(4)
	#
	# This happens in-memory:
	#
	# ~~~raw
	# f.....g.....o..
	# .u...n.b...m.t.
	# ..c.i...e.e...h
	# ...k.....h.....
	# ~~~
	#
	# Therefore, yielding the ciphertext : "fgounbmtcieehkh"
	#
	#     assert "fuckingbehemoth".railfence(4) == "fgounbmtcieehkh"
	fun railfence(depth: Int): Text do
		var lines = new Array[FlatBuffer].with_capacity(depth)
		var up = false
		for i in [0..depth[ do
			lines[i] = new FlatBuffer.with_capacity(length)
		end
		var curr_depth = 0
		for i in chars do
			for j in [0..depth[ do
				if j == curr_depth then
					lines[j].add i
				else
					lines[j].add '.'
				end
			end
			if up then
				curr_depth -= 1
			else
				curr_depth += 1
			end
			if curr_depth == 0 then
				up = false
			end
			if curr_depth == (depth - 1) then
				up = true
			end
		end
		var r = new FlatBuffer.with_capacity(length)
		for i in lines do
			r.append i.to_s.replace(".", "")
		end
		return r.to_s
	end

	# Transforms a rail-fence-encrypted Text to its original
	#
	#     assert "fgounbmtcieehkh".unrail(4) == "fuckingbehemoth"
	fun unrail(depth: Int): Text do
		var dots = "." * length
		var arr = new FlatBuffer.from(dots)
		var start = 0
		var paces = depth.unrail_paces
		for i in [0..depth[ do
			var lp = paces[i].first
			var rp = paces[i].second
			var pos = i
			var l = true
			while pos < length do
				arr[pos] = chars[start]
				if l then
					pos += lp
					l = false
				else
					pos += rp
					l = true
				end
				start += 1
			end
		end
		return arr.to_s
	end

	# Vigenere encoder on ASCII letters.
	#
	# Only the letters in '[A-Za-z]' are encoded while keeping the case.
	#
	#     assert "Hello, World!".vigenere("abc") == "Hfnlp, Yosnd!"
	#
	# REQUIRE `key` contains only lowercases '[a-z]'
	fun vigenere(key: String): String
	do
		var res = new Buffer
		res.enlarge(length)
		var i = 0
		for c in self do
			var k = key[i%key.length]
			assert k >= 'a' and k <= 'z'
			if c.is_letter then
				var d = k.code_point - 'a'.code_point
				c = c.rot(d)
				i += 1
			end
			res.add c
		end
		return res.to_s
	end

	# Vigenere decoder on ASCII letters.
	#
	# Only the letters in '[A-Za-z]' are decoded while keeping the case.
	#
	#     assert "Hfnlp, Yosnd!".uvigenere("abc") == "Hello, World!"
	#
	# REQUIRE `key` contains only lowercases '[a-z]'
	fun uvigenere(key: String): String
	do
		var res = new Buffer
		res.enlarge(length)
		var i = 0
		for c in self do
			var k = key[i%key.length]
			assert k >= 'a' and k <= 'z'
			if c.is_letter then
				var d = k.code_point - 'a'.code_point
				c = c.rot(-d)
				i += 1
			end
			res.add c
		end
		return res.to_s
	end
end

redef class Bytes
	# Computes the edit/hamming distance of two sequences of bytes.
	#
	#     assert "this is a test".to_bytes.hamming_distance("wokka wokka!!!".bytes) == 37
	#     assert "this is a test".to_bytes.hamming_distance("this is a test".bytes) == 0
	#
	fun hamming_distance(other: SequenceRead[Int]): Int do
		var diff = 0
		for idx in self.length.times do
			var res_byte = self[idx] ^ other[idx]
			for bit in [0..8[ do
				if res_byte & 1 == 1 then diff += 1
				res_byte = res_byte >> 1
			end
		end
		return diff
	end
end

redef class Int
	# Generates the paces for each depth.
	#
	# Each entry of the returned array is a couple of the first pace
	# and the second one, they are alternated when deciphering a rail-encrypted string.
	#
	# Say we have the encrypted string "fgounbmtcieehkh" on 4 rails
	#
	# To find the distance between each character on the original railed
	# string, we need to compute the extremes.
	#
	# The extremes always have a distance of `depth - 1`, multiplied by 2, no pairing.
	#
	# In the example, that would be : [(4 - 1) * 2, (4 - 1) * 2] => [6,6]
	#
	# For every rail in-between, the first distance is the largest absolute value
	# of the difference between the current depth and the extremes, multiplied by 2.
	#
	# Its pair is the distance of maximum and the distance yielded by the previous
	# calculation.
	#
	# In our example, that would be :
	#
	# Maximums : (4 - 1) * 2 = 3 * 2 => [6,6]
	# In between : Distance for depth 2 : max(2 - 1, 4 - 2) => 2
	# The calculation yields the couple [(2 * 2), 6 - 4] => [4, 2]
	# The symmetric couple is reversed : [2, 4]
	#
	# In fine, the example yields the array : [[6,6], [4,2], [2,4], [6,6]]
	#
	# In the end, our string is read using the generated array
	#
	# SEE: `Text::unrail` for how the array is used
	private fun unrail_paces: Array[Couple[Int, Int]] do
		var ret = new Array[Couple[Int,Int]].with_capacity(self)
		var extremes = new Couple[Int, Int]((self - 1) * 2, (self - 1) * 2)
		for i in [0..self[ do
			ret.add extremes
		end
		var mid = ((self.to_f)/2.0).floor.to_i
		for i in [1 .. mid[ do
			var rd = i + 1
			var lodepth = self - rd
			var hidepth = (rd - self).abs
			var dd: Int
			if hidepth > lodepth then
				dd = hidepth * 2
			else
				dd = lodepth * 2
			end
			var cp = new Couple[Int, Int](dd, extremes.first-dd)
			var ccp = new Couple[Int, Int](extremes.first - dd, dd)

			ret[i] = cp
			ret[self - rd] = ccp
		end
		if not self.is_even then
			ret[mid] = new Couple[Int, Int](extremes.first/2, extremes.first/2)
		end
		return ret
	end
end
lib/crypto/basic_ciphers.nit:15,1--289,3