bitster 0.0.1c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +4 -0
  3. data/.coveralls.yml +1 -0
  4. data/.gitignore +3 -0
  5. data/.rspec +2 -0
  6. data/.travis.yml +6 -0
  7. data/Gemfile +4 -0
  8. data/README.md +25 -0
  9. data/Rakefile +1 -0
  10. data/bitster.gemspec +37 -0
  11. data/coverage/.last_run.json +5 -0
  12. data/coverage/.resultset.json +363 -0
  13. data/coverage/.resultset.json.lock +0 -0
  14. data/coverage/assets/0.10.0/application.css +799 -0
  15. data/coverage/assets/0.10.0/application.js +1707 -0
  16. data/coverage/assets/0.10.0/colorbox/border.png +0 -0
  17. data/coverage/assets/0.10.0/colorbox/controls.png +0 -0
  18. data/coverage/assets/0.10.0/colorbox/loading.gif +0 -0
  19. data/coverage/assets/0.10.0/colorbox/loading_background.png +0 -0
  20. data/coverage/assets/0.10.0/favicon_green.png +0 -0
  21. data/coverage/assets/0.10.0/favicon_red.png +0 -0
  22. data/coverage/assets/0.10.0/favicon_yellow.png +0 -0
  23. data/coverage/assets/0.10.0/loading.gif +0 -0
  24. data/coverage/assets/0.10.0/magnify.png +0 -0
  25. data/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  26. data/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  27. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  28. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  29. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  30. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  31. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  32. data/coverage/assets/0.10.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  33. data/coverage/assets/0.10.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
  34. data/coverage/assets/0.10.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  35. data/coverage/assets/0.10.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
  36. data/coverage/assets/0.10.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
  37. data/coverage/assets/0.10.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  38. data/coverage/index.html +2290 -0
  39. data/examples/bitster.rb +58 -0
  40. data/examples/bitster.txt +9 -0
  41. data/examples/bitster_simple.rb +27 -0
  42. data/lib/bitster.rb +14 -0
  43. data/lib/bitster/crypto_math.rb +132 -0
  44. data/lib/bitster/rsa_key_pair.rb +87 -0
  45. data/lib/bitster/rsa_machine.rb +32 -0
  46. data/lib/bitster/rsa_private_key.rb +31 -0
  47. data/lib/bitster/rsa_pub_key.rb +28 -0
  48. data/lib/bitster/var_helpers.rb +13 -0
  49. data/lib/bitster/version.rb +3 -0
  50. metadata +232 -0
@@ -0,0 +1,58 @@
1
+ $dev = true # flip this if running against an actually installed gem
2
+
3
+ if !$dev
4
+ require 'bitster'
5
+ else
6
+ require_relative '../lib/bitster/version'
7
+ require_relative '../lib/bitster/crypto_math'
8
+ require_relative '../lib/bitster/var_helpers'
9
+ require_relative '../lib/bitster/rsa_key_pair'
10
+ require_relative '../lib/bitster/rsa_pub_key'
11
+ require_relative '../lib/bitster/rsa_private_key'
12
+ require_relative '../lib/bitster/rsa_machine'
13
+ end
14
+
15
+ ciphertext = Array.new
16
+ result = Array.new
17
+
18
+ begin
19
+ plaintext = File.read(ARGV[0]).split("")
20
+ rescue
21
+ if $stdin.tty?
22
+ plaintext = ("C"*32).split("")
23
+ else
24
+ plaintext = ARGF.read.split("")
25
+ end
26
+ end
27
+
28
+ key_len = 1024
29
+ print "[*] Generating a new RSA key-pair with modulus #{key_len}..."
30
+ t0 = Time.now.to_i
31
+ pair = Bitster::RSAKeyPair.new(key_len)
32
+ t1 = Time.now.to_i
33
+ puts " done; time elapsed: #{t1 - t0}s."
34
+
35
+ machine = Bitster::RSAMachine.new(:keypair => pair)
36
+
37
+ print "[*] Encrypting..."
38
+ t0 = Time.now.to_i
39
+ plaintext.each do |c|
40
+ ciphertext << machine.encrypt(c.ord)
41
+ end
42
+ t1 = Time.now.to_i
43
+ puts " done; time elapsed: #{t1 - t0}s."
44
+
45
+
46
+ print "[*] Decrypting..."
47
+ t0 = Time.now.to_i
48
+ ciphertext.each do |c|
49
+ result << machine.decrypt(c).chr
50
+ end
51
+ t1 = Time.now.to_i
52
+ puts " done; time elapsed: #{t1 - t0}s."
53
+
54
+ puts "[*] Result:"
55
+ puts "-"*80
56
+ puts result.join
57
+ puts "-"*80
58
+ puts "[*] -END-"
@@ -0,0 +1,9 @@
1
+ RSA is one of the first practical public-key cryptosystems and is widely used
2
+ for secure data transmission. In such a cryptosystem, the encryption key is
3
+ public and differs from the decryption key which is kept secret. In RSA, this
4
+ asymmetry is based on the practical difficulty of factoring the product of two
5
+ large prime numbers, the factoring problem. RSA is made of the initial letters
6
+ of the surnames of Ron Rivest, Adi Shamir, and Leonard Adleman, who first
7
+ publicly described the algorithm in 1977. Clifford Cocks, an English mathe-
8
+ matician working for the UK intelligence agency GCHQ, had developed an equi-
9
+ valent system in 1973, but it was not declassified until 1997.
@@ -0,0 +1,27 @@
1
+ $dev = true # flip this if running against an actually installed gem
2
+
3
+ if !$dev
4
+ require 'bitster'
5
+ else
6
+ require_relative '../lib/bitster/version'
7
+ require_relative '../lib/bitster/crypto_math'
8
+ require_relative '../lib/bitster/var_helpers'
9
+ require_relative '../lib/bitster/rsa_key_pair'
10
+ require_relative '../lib/bitster/rsa_pub_key'
11
+ require_relative '../lib/bitster/rsa_private_key'
12
+ require_relative '../lib/bitster/rsa_machine'
13
+ end
14
+
15
+ key_pair = Bitster::RSAKeyPair.new(1024)
16
+ machine = Bitster::RSAMachine.new(:keypair => key_pair)
17
+
18
+ ciphertext = %w(H E L L O).collect do |char|
19
+ machine.encrypt(char.ord)
20
+ end
21
+
22
+ plaintext = ciphertext.collect do |ascii_code|
23
+ machine.decrypt(ascii_code).chr
24
+ end.join('')
25
+
26
+ puts plaintext
27
+
@@ -0,0 +1,14 @@
1
+ require 'bitster/version'
2
+ require 'bitster/crypto_math'
3
+ require 'bitster/var_helpers'
4
+ require 'bitster/rsa_key_pair'
5
+ require 'bitster/rsa_pub_key'
6
+ require 'bitster/rsa_private_key'
7
+ require 'bitster/rsa_machine'
8
+
9
+
10
+ require 'json'
11
+
12
+ module Bitster
13
+ include self::CryptoMath
14
+ end
@@ -0,0 +1,132 @@
1
+ module Bitster
2
+
3
+ # This module implements mathematical functions needed by the RSA layer,
4
+ # i.e. primality tests, modular arithmetic, and random odd number generation.
5
+ #
6
+ # ToDo: Error handling (with custom Exception class, etc.)
7
+ #
8
+ module CryptoMath
9
+
10
+ # This function performs what is known as Modular exponentiation
11
+ # https://en.wikipedia.org/wiki/Modular_exponentiation
12
+ #
13
+ # Modular exponentiation are easy to compute, even when the numbers
14
+ # involved are enormous.
15
+ #
16
+ def modular_pow(base, exponent, modulus)
17
+ return nil if modulus == 1
18
+ result = 1
19
+ base = base % modulus
20
+ while exponent > 0 do
21
+ if (exponent % 2) == 1
22
+ result = (result * base) % modulus
23
+ end
24
+ exponent = exponent >> 1
25
+ base = (base * base) % modulus
26
+ end
27
+ result
28
+ end
29
+
30
+ # This function just combines Fermat test and Rabin-Miller test.
31
+ # If both witness the primality, we consider the argument a
32
+ # probable prime
33
+ #
34
+ # ToDo: How to calculate an optimal number of RM rounds instead of 7?
35
+ #
36
+ def probable_prime?(p, k=7)
37
+ fermat_prime?(p) && rm_prime?(p, k)
38
+ end
39
+
40
+ # This is Fermat primality test.
41
+ # https://en.wikipedia.org/wiki/Fermat_primality_test
42
+ #
43
+ # ToDo: How to really choose "a" and how many iterations to run?
44
+ #
45
+ def fermat_prime?(p)
46
+ raise ArgumentError, 'Argument must be an Integer greater than 3' unless p.is_a?(Integer) && (p>3)
47
+ [p-1, p/2, p/3, p/4, 1].each do |a|
48
+ # return false if (a**(p-1) % p) != (1 % p)
49
+ return false if modular_pow(a, (p-1), p) != (1 % p)
50
+ end
51
+ true
52
+ end
53
+
54
+ # This is Rabin-Miller primality test
55
+ # https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
56
+ #
57
+ def rm_prime?(n, k)
58
+ r=0; d=0
59
+ (1..128).each do |i|
60
+ d = n / (2**i)
61
+ r = i
62
+ break unless (d % 2) == 0
63
+ end
64
+ k.times do
65
+ flg = false
66
+ a = rand(2..(n-2))
67
+ x = modular_pow(a, d, n)
68
+ if (x == 1) || (x == (n - 1))
69
+ next
70
+ end
71
+ (r-1).times do
72
+ x = modular_pow(x, 2, n)
73
+ return false if x == 1
74
+ if x == (n - 1)
75
+ flg = true
76
+ break
77
+ end
78
+ end
79
+ next if flg
80
+ return false
81
+ end
82
+ true
83
+ end
84
+
85
+ # This function generates a random odd integer in a range of
86
+ # 2^(bits-1) ... 2^(bits)
87
+ #
88
+ # ToDo: What should the minimum really be?
89
+ #
90
+ def gen_odd(bits)
91
+ max = 2**bits
92
+ min = 2**(bits-1)
93
+ r = rand(min..max)
94
+ return r - 1 if r%2 == 0
95
+ r
96
+ end
97
+
98
+ # This function calculates the Modular multiplicative inverse
99
+ # which is needed in the key generation process.
100
+ # https://en.wikipedia.org/wiki/Modular_multiplicative_inverse
101
+ #
102
+ def modular_multiplicative_inverse(a, n)
103
+ t = 0
104
+ nt = 1
105
+ r = n
106
+ nr = a % n
107
+
108
+ if n < 0
109
+ n = -n
110
+ end
111
+ if a < 0
112
+ a = n - (-a % n)
113
+ end
114
+ while nr != 0 do
115
+ quot = 0
116
+ quot = (r/nr) unless (r/nr) == 0
117
+ tmp = nt; nt = t - quot*nt; t = tmp
118
+ tmp = nr; nr = r - quot*nr; r = tmp
119
+ end
120
+ if r > 1
121
+ raise StandardError, "#{a} and #{n} are not coprimes, can't find MMI"
122
+ end
123
+ if t < 0
124
+ t += n
125
+ end
126
+ t
127
+ end
128
+
129
+ extend self
130
+
131
+ end
132
+ end
@@ -0,0 +1,87 @@
1
+ module Bitster
2
+
3
+ # This class represents a RSA key-pair. The most important feature is the
4
+ # generation of the key-pair, so it is an implementation of the process
5
+ # outlined in https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Key_generation
6
+ #
7
+ class RSAKeyPair
8
+
9
+ class RSAKeyPairError < StandardError
10
+ end
11
+
12
+ attr_reader :len, :shorter, :p, :q, :n, :k, :e, :private_key, :public_key
13
+
14
+ def initialize(len)
15
+ @len = len
16
+
17
+ @shorter = rand(0..1)
18
+ @p = gen_p
19
+ @q = gen_q
20
+ @n = @p * @q # modulus
21
+ @k = gen_totient
22
+ @e = gen_e # pubkey exponent
23
+ @d = gen_d # prikey exponent
24
+
25
+ @private_key = RSAPrivateKey.new(@p, @q, @d, @len)
26
+ @public_key = RSAPubKey.new(@n, @e, @len)
27
+
28
+ end
29
+
30
+ private
31
+ include CryptoMath
32
+
33
+ # ToDo: what should the length difference of p and q really be?
34
+ def gen_p
35
+ handle_exceptions do
36
+ len_p = @len/2
37
+ len_p -= rand(2..4) if @shorter == 0
38
+ loop do
39
+ p = gen_odd(len_p)
40
+ return p if probable_prime?(p)
41
+ end
42
+ end
43
+ end
44
+
45
+ # ToDo: what should the length difference of p and q really be?
46
+ def gen_q
47
+ handle_exceptions do
48
+ len_q = @len/2
49
+ len_q -= rand(2..4) if @shorter == 1
50
+ loop do
51
+ q = gen_odd(len_q)
52
+ return q if probable_prime?(q)
53
+ end
54
+ end
55
+ end
56
+
57
+ def gen_totient
58
+ handle_exceptions do
59
+ (@p-1)*(@q-1)
60
+ end
61
+ end
62
+
63
+ # ToDo: what should the lower bound really be?
64
+ def gen_e
65
+ handle_exceptions do
66
+ loop do
67
+ e = rand(4..@k)
68
+ return e if e.gcd(@k) == 1
69
+ end
70
+ end
71
+ end
72
+
73
+ def gen_d
74
+ handle_exceptions do
75
+ modular_multiplicative_inverse(e, k)
76
+ end
77
+ end
78
+
79
+ def handle_exceptions
80
+ begin
81
+ yield
82
+ rescue StandardError => e
83
+ raise RSAKeyPairError, "Exception in RSAKeyPair: #{e}"
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,32 @@
1
+ module Bitster
2
+
3
+ # This class implements RSA encryption and decryption functions.
4
+ # It is initialized with necessary keys, represented as instances
5
+ # of their according classes.
6
+ #
7
+ class RSAMachine
8
+ attr_accessor :pubkey, :prikey
9
+
10
+ def initialize(opts={})
11
+ @pubkey = opts[:pubkey] if opts.has_key?(:pubkey)
12
+ @prikey = opts[:prikey] if opts.has_key?(:prikey)
13
+ if opts.has_key?(:keypair)
14
+ @pubkey = opts[:keypair].public_key
15
+ @prikey = opts[:keypair].private_key
16
+ end
17
+ end
18
+
19
+ # https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Encryption
20
+ #
21
+ def encrypt(plaintext_msg_code)
22
+ CryptoMath::modular_pow(plaintext_msg_code, @pubkey.exponent, @pubkey.modulus)
23
+ end
24
+
25
+ # https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Decryption
26
+ #
27
+ def decrypt(ciphertext_msg_code)
28
+ CryptoMath::modular_pow(ciphertext_msg_code, @prikey.exponent, @prikey.modulus)
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ module Bitster
2
+
3
+ # This class represents RSA private key and provides various
4
+ # formatting and similar helper methods associated with it.
5
+ #
6
+ class RSAPrivateKey
7
+
8
+ attr_reader :modulus, :exponent, :len, :p, :q
9
+
10
+ def initialize(p, q, exponent, len)
11
+ @exponent = exponent
12
+ @modulus = p*q
13
+ @p = p; @q = q
14
+ @len = len
15
+ end
16
+
17
+ def get_hash
18
+ { modulus: pad(@modulus, 16, @len), exponent: pad(@exponent, 16, @len) }
19
+ end
20
+
21
+ def get_json
22
+ JSON.pretty_generate get_hash
23
+ end
24
+
25
+ private
26
+ include VarHelpers
27
+
28
+ end
29
+ end
30
+
31
+
@@ -0,0 +1,28 @@
1
+ module Bitster
2
+
3
+ # This class represents RSA public key and provides various
4
+ # formatting and similar helper methods associated with it.
5
+ #
6
+ class RSAPubKey
7
+
8
+ attr_reader :modulus, :exponent, :len
9
+
10
+ def initialize(modulus, exponent, len)
11
+ @modulus = modulus
12
+ @exponent = exponent
13
+ @len = len
14
+ end
15
+
16
+ def get_hash
17
+ { modulus: pad(@modulus, 16, @len), exponent: pad(@exponent, 16, @len) }
18
+ end
19
+
20
+ def get_json
21
+ JSON.pretty_generate get_hash
22
+ end
23
+
24
+ private
25
+ include VarHelpers
26
+
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ module Bitster
2
+ module VarHelpers
3
+ include Math
4
+
5
+ def pad(num, base, len)
6
+ digits = (len*log(2)) / (log(base))
7
+ num.to_s(base).rjust(digits, '0')
8
+ end
9
+
10
+ extend self
11
+
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Bitster
2
+ VERSION='0.0.1c'
3
+ end