zweifische 1.0.1

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.
@@ -0,0 +1,35 @@
1
+ #ifndef _h_twofish
2
+
3
+ #define _h_twofish
4
+
5
+ #ifdef __cplusplus
6
+ extern "C" {
7
+ #endif
8
+
9
+ #define u32 unsigned int
10
+ #define BYTE unsigned char
11
+
12
+ struct twofish;
13
+
14
+ struct twofish *twofish_256_ecb_init(BYTE key[], BYTE iv[16]);
15
+ struct twofish *twofish_256_cbc_init(BYTE key[], BYTE iv[16]);
16
+
17
+ struct twofish *twofish_192_ecb_init(BYTE key[], BYTE iv[16]);
18
+ struct twofish *twofish_192_cbc_init(BYTE key[], BYTE iv[16]);
19
+
20
+ struct twofish *twofish_128_ecb_init(BYTE key[], BYTE iv[16]);
21
+ struct twofish *twofish_128_cbc_init(BYTE key[], BYTE iv[16]);
22
+
23
+ void twofish_free(struct twofish **pctx);
24
+
25
+ int twofish_encrypt_update(struct twofish *ctx, BYTE plain_text[], u32 text_len, BYTE crypted_text[], u32 crypt_len);
26
+ int twofish_encrypt_final(struct twofish *ctx, BYTE plain_text[], u32 text_len, BYTE crypted_text[], u32 crypt_len);
27
+
28
+ int twofish_decrypt_update(struct twofish *ctx, BYTE crypted_text[], u32 crypted_len, BYTE plain_text[], u32 text_len);
29
+ int twofish_decrypt_final(struct twofish *ctx, BYTE crypted_text[], u32 crypted_len, BYTE plain_text[], u32 text_len);
30
+
31
+ #ifdef __cplusplus
32
+ }
33
+ #endif
34
+
35
+ #endif
@@ -0,0 +1,184 @@
1
+ #include <ruby.h>
2
+ #include "twofish.h"
3
+
4
+ #define LEN_ERR_MSG "Provided string must have length at least 16 bytes. " \
5
+ "You may consider to use any available padding schemes under " \
6
+ "Zweifische (e.g. z.encrypt(data, pad: Zweifische::ZeroPadding)), " \
7
+ "or you can just explicitly provide string with (multiple of) " \
8
+ "16 bytes in length."
9
+
10
+ #define LEN_PADDED_ERR_MSG "There's error in string length, it should has "\
11
+ "(multiple of) 16 bytes in length after padding, but it's not."
12
+
13
+ #define assert_string_type(key) if (TYPE(key) != T_STRING) { rb_raise(rb_eTypeError, "type should be string"); }
14
+
15
+ #define GET_C_STRPTR(val, str) { assert_string_type(val); str = (unsigned char *)StringValuePtr(val); } while (0)
16
+
17
+ #define GET_C_STRPTR_AND_LEN(val, str, strlen) { GET_C_STRPTR(val, str); strlen = RSTRING_LEN(val); } while (0)
18
+
19
+ void cipher_free(void *st);
20
+
21
+ static const rb_data_type_t twofish_ctx_type = {
22
+ "twofish_ctx",
23
+ { 0, cipher_free, 0, },
24
+ 0, 0,
25
+ RUBY_TYPED_FREE_IMMEDIATELY,
26
+ };
27
+
28
+ void cipher_free(void *st)
29
+ {
30
+ struct twofish *twofish_ctx = (struct twofish *)st;
31
+ twofish_free(&twofish_ctx);
32
+ }
33
+
34
+ #define CIPHER_ECB_INIT(self, key, len) { \
35
+ unsigned char *sKey; \
36
+ struct twofish *ctx; \
37
+ VALUE twofish_ctx; \
38
+ \
39
+ GET_C_STRPTR(key, sKey); \
40
+ \
41
+ ctx = twofish_##len##_ecb_init(sKey, (void *)0); \
42
+ \
43
+ twofish_ctx = TypedData_Wrap_Struct(rb_cData, &twofish_ctx_type, ctx); \
44
+ rb_ivar_set(self, rb_intern("twofish_ctx"), twofish_ctx); \
45
+ \
46
+ return Qnil; \
47
+ }
48
+
49
+ static VALUE cipher_256_ecb_init(VALUE self, VALUE key) CIPHER_ECB_INIT(self, key, 256)
50
+ static VALUE cipher_192_ecb_init(VALUE self, VALUE key) CIPHER_ECB_INIT(self, key, 192)
51
+ static VALUE cipher_128_ecb_init(VALUE self, VALUE key) CIPHER_ECB_INIT(self, key, 128)
52
+
53
+
54
+ #define CIPHER_CBC_INIT(self, key, iv, len) { \
55
+ unsigned char *sKey; \
56
+ unsigned char *sIV; \
57
+ struct twofish *ctx; \
58
+ VALUE twofish_ctx; \
59
+ \
60
+ GET_C_STRPTR(key, sKey); \
61
+ \
62
+ GET_C_STRPTR(iv, sIV); \
63
+ \
64
+ ctx = twofish_##len##_cbc_init(sKey, sIV); \
65
+ \
66
+ twofish_ctx = TypedData_Wrap_Struct(rb_cData, &twofish_ctx_type, ctx); \
67
+ rb_ivar_set(self, rb_intern("twofish_ctx"), twofish_ctx); \
68
+ \
69
+ return Qnil; \
70
+ }
71
+
72
+ static VALUE cipher_256_cbc_init(VALUE self, VALUE key, VALUE iv) CIPHER_CBC_INIT(self, key, iv, 256)
73
+ static VALUE cipher_192_cbc_init(VALUE self, VALUE key, VALUE iv) CIPHER_CBC_INIT(self, key, iv, 192)
74
+ static VALUE cipher_128_cbc_init(VALUE self, VALUE key, VALUE iv) CIPHER_CBC_INIT(self, key, iv, 128)
75
+
76
+
77
+ #define CIPHER_OP(self, data, operation) { \
78
+ unsigned char *sData, *targetData; \
79
+ unsigned int lData, lTargetData; \
80
+ int result; \
81
+ struct twofish *ctx; \
82
+ VALUE twofish_ctx, targetText; \
83
+ \
84
+ GET_C_STRPTR_AND_LEN(data, sData, lData); \
85
+ \
86
+ twofish_ctx = rb_ivar_get(self, rb_intern("twofish_ctx")); \
87
+ TypedData_Get_Struct(twofish_ctx, struct twofish, &twofish_ctx_type, ctx); \
88
+ \
89
+ lTargetData = ((lData / 16) + 1) * 16; \
90
+ targetData = ALLOC_N(unsigned char, lTargetData); \
91
+ result = operation(ctx, sData, lData, targetData, lTargetData); \
92
+ \
93
+ if (result < 0) { \
94
+ rb_raise(rb_eRuntimeError, LEN_ERR_MSG); \
95
+ } \
96
+ \
97
+ targetText = rb_str_new((const char *)targetData, result); \
98
+ xfree(targetData); \
99
+ return targetText; \
100
+ }
101
+
102
+ static VALUE cipher_encrypt_update(VALUE self, VALUE data) CIPHER_OP(self, data, twofish_encrypt_update)
103
+ static VALUE cipher_encrypt_final(VALUE self, VALUE data) CIPHER_OP(self, data, twofish_encrypt_final)
104
+
105
+ static VALUE cipher_encrypt_final_with_pad(VALUE self, VALUE data, VALUE pad)
106
+ {
107
+ unsigned char *sData, *targetData;
108
+ unsigned int lData, lTargetData;
109
+ int result;
110
+ struct twofish *ctx;
111
+ VALUE twofish_ctx, crypted_text;
112
+
113
+ GET_C_STRPTR_AND_LEN(data, sData, lData);
114
+
115
+ twofish_ctx = rb_ivar_get(self, rb_intern("twofish_ctx"));
116
+ TypedData_Get_Struct(twofish_ctx, struct twofish, &twofish_ctx_type, ctx);
117
+
118
+ lTargetData = ((lData / 16) + 1) * 16;
119
+ targetData = ALLOC_N(unsigned char, lTargetData);
120
+ result = twofish_encrypt_final(ctx, sData, lData, targetData, lTargetData);
121
+
122
+ if (result < 0) {
123
+ VALUE padlen = INT2FIX(-1 * result);
124
+ VALUE padstr = rb_funcallv_public(pad, rb_intern("pad"), 1, &padlen);
125
+
126
+ rb_str_append(data, padstr);
127
+ GET_C_STRPTR_AND_LEN(data, sData, lData);
128
+ xfree(targetData);
129
+
130
+ lTargetData = ((lData / 16) + 1) * 16;
131
+ targetData = ALLOC_N(unsigned char, lTargetData);
132
+ result = twofish_encrypt_final(ctx, sData, lData, targetData, lTargetData);
133
+
134
+ if (result < 0) {
135
+ rb_raise(rb_eRuntimeError, LEN_PADDED_ERR_MSG);
136
+ }
137
+ }
138
+
139
+ crypted_text = rb_str_new((const char *)targetData, result);
140
+ xfree(targetData);
141
+
142
+ return crypted_text;
143
+ }
144
+
145
+ static VALUE cipher_decrypt_update(VALUE self, VALUE crypted) CIPHER_OP(self, crypted, twofish_decrypt_update)
146
+ static VALUE cipher_decrypt_final(VALUE self, VALUE crypted) CIPHER_OP(self, crypted, twofish_decrypt_final)
147
+
148
+ void Init_zweifische()
149
+ {
150
+ VALUE mZweifische,
151
+ cCipher256ecb,
152
+ cCipher256cbc,
153
+ cCipher192ecb,
154
+ cCipher192cbc,
155
+ cCipher128ecb,
156
+ cCipher128cbc;
157
+
158
+ mZweifische = rb_define_module("Zweifische");
159
+
160
+ cCipher256ecb = rb_define_class_under(mZweifische, "Cipher256ecb", rb_cObject);
161
+ rb_define_method(cCipher256ecb, "initialize", cipher_256_ecb_init, 1);
162
+
163
+ rb_define_method(cCipher256ecb, "encrypt_update", cipher_encrypt_update, 1);
164
+ rb_define_method(cCipher256ecb, "c_encrypt_final", cipher_encrypt_final, 1);
165
+ rb_define_method(cCipher256ecb, "c_encrypt_final_with_pad", cipher_encrypt_final_with_pad, 2);
166
+
167
+ rb_define_method(cCipher256ecb, "decrypt_update", cipher_decrypt_update, 1);
168
+ rb_define_method(cCipher256ecb, "c_decrypt_final", cipher_decrypt_final, 1);
169
+
170
+ cCipher256cbc = rb_define_class_under(mZweifische, "Cipher256cbc", cCipher256ecb);
171
+ rb_define_method(cCipher256cbc, "initialize", cipher_256_cbc_init, 2);
172
+
173
+ cCipher192ecb = rb_define_class_under(mZweifische, "Cipher192ecb", cCipher256ecb);
174
+ rb_define_method(cCipher192ecb, "initialize", cipher_192_ecb_init, 1);
175
+
176
+ cCipher192cbc = rb_define_class_under(mZweifische, "Cipher192cbc", cCipher256ecb);
177
+ rb_define_method(cCipher192cbc, "initialize", cipher_192_cbc_init, 2);
178
+
179
+ cCipher128ecb = rb_define_class_under(mZweifische, "Cipher128ecb", cCipher256ecb);
180
+ rb_define_method(cCipher128ecb, "initialize", cipher_128_ecb_init, 1);
181
+
182
+ cCipher128cbc = rb_define_class_under(mZweifische, "Cipher128cbc", cCipher256ecb);
183
+ rb_define_method(cCipher128cbc, "initialize", cipher_128_cbc_init, 2);
184
+ }
data/lib/zweifische.rb ADDED
@@ -0,0 +1,13 @@
1
+ require "zweifische/version"
2
+
3
+ module Zweifische
4
+ end
5
+
6
+ require "zweifische/ansi_x_923_padding"
7
+ require "zweifische/iso_iec_7816_4_padding"
8
+ require "zweifische/pkcs7_padding"
9
+ require "zweifische/zero_padding"
10
+
11
+ require "zweifische/zweifische"
12
+
13
+ require "zweifische/cipher_256_ecb"
@@ -0,0 +1,36 @@
1
+ module Zweifische
2
+ class AnsiX923Padding
3
+ class << self
4
+ def pad(num)
5
+ raise ArgumentError.new("max pad is 16 bytes") if num > 15 || num < 0
6
+ return "" if num == 0
7
+ 0x00.chr * (num - 1) + num.chr
8
+ end
9
+
10
+ def unpad(text)
11
+ numpad = numpad(text)
12
+ if assert_pad(text, numpad, 0x00.chr)
13
+ return text[0..(-1 * (numpad + 1))]
14
+ end
15
+ text
16
+ end
17
+
18
+ private
19
+
20
+ def assert_pad(text, numpad, char)
21
+ text
22
+ .split("")
23
+ .reverse[1..numpad - 1]
24
+ .all? { |c| c.eql?(char) }
25
+ end
26
+
27
+ def numpad(text)
28
+ text
29
+ .force_encoding(Encoding::ASCII_8BIT)
30
+ .split("")
31
+ .last
32
+ .ord
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,22 @@
1
+ module Zweifische
2
+ class Cipher256ecb
3
+ def encrypt_final(plain_text, pad: nil)
4
+ if pad && pad.respond_to?(:pad)
5
+ c_encrypt_final_with_pad(plain_text, pad)
6
+ else
7
+ c_encrypt_final(plain_text)
8
+ end
9
+ end
10
+
11
+ def decrypt_final(crypted_text, pad: nil)
12
+ plain_text = c_decrypt_final(crypted_text)
13
+ if pad && pad.respond_to?(:unpad)
14
+ return pad.unpad(plain_text)
15
+ end
16
+ plain_text
17
+ end
18
+
19
+ alias_method :encrypt, :encrypt_final
20
+ alias_method :decrypt, :decrypt_final
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ module Zweifische
2
+ class ISOIEC78164Padding
3
+ def self.pad(num)
4
+ raise ArgumentError.new("max pad is 16 bytes") if num > 15 || num < 0
5
+ return "" if num == 0
6
+ 0x80.chr + (0x00.chr * (num - 1))
7
+ end
8
+
9
+ def self.unpad(text)
10
+ wpad = text.split("").reverse[0..15]
11
+ count = wpad.each_with_index do |ch, idx|
12
+ return text if ch != 0.chr && ch != 0x80.chr
13
+ break idx if ch == 0x80.chr
14
+ end
15
+ text[0..(-1 * (count + 2))]
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ module Zweifische
2
+ class PKCS7Padding < AnsiX923Padding
3
+ def self.pad(num)
4
+ raise ArgumentError.new("max pad is 16 bytes") if num > 15 || num < 0
5
+ num.chr * num
6
+ end
7
+
8
+ def self.unpad(text)
9
+ numpad = numpad(text)
10
+ if assert_pad(text, numpad, numpad.chr)
11
+ return text[0..(-1 * (numpad + 1))]
12
+ end
13
+ text
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module Zweifische
2
+ VERSION = "1.0.1"
3
+ end
@@ -0,0 +1,12 @@
1
+ module Zweifische
2
+ class ZeroPadding
3
+ def self.pad(num)
4
+ raise ArgumentError.new("max pad is 16 bytes") if num > 15 || num < 0
5
+ 0x00.chr * num
6
+ end
7
+
8
+ def self.unpad(text)
9
+ text.gsub(/\x00+\z/, "")
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,29 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "zweifische/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "zweifische"
8
+ spec.version = Zweifische::VERSION
9
+ spec.authors = ["Nurahmadie"]
10
+ spec.email = ["nurahmadie@gmail.com"]
11
+
12
+ spec.summary = %q{Ruby binding for @drewcsillag twofish implementation}
13
+ spec.homepage = "https://github.com/fudanchii/twofish"
14
+
15
+ # Specify which files should be added to the gem when it is released.
16
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
17
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+ spec.extensions = ["ext/zweifische/extconf.rb"]
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.16"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "rake-compiler", "> 0"
28
+ spec.add_development_dependency "minitest", "~> 5.0"
29
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zweifische
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nurahmadie
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-09-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake-compiler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">"
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ description:
70
+ email:
71
+ - nurahmadie@gmail.com
72
+ executables: []
73
+ extensions:
74
+ - ext/zweifische/extconf.rb
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - ".travis.yml"
79
+ - Gemfile
80
+ - LICENSE
81
+ - README.md
82
+ - Rakefile
83
+ - bin/console
84
+ - bin/setup
85
+ - ext/zweifische/LICENSE
86
+ - ext/zweifische/Makefile
87
+ - ext/zweifische/extconf.rb
88
+ - ext/zweifische/tables.h
89
+ - ext/zweifische/twofish.c
90
+ - ext/zweifische/twofish.h
91
+ - ext/zweifische/zweifische.c
92
+ - lib/zweifische.rb
93
+ - lib/zweifische/ansi_x_923_padding.rb
94
+ - lib/zweifische/cipher_256_ecb.rb
95
+ - lib/zweifische/iso_iec_7816_4_padding.rb
96
+ - lib/zweifische/pkcs7_padding.rb
97
+ - lib/zweifische/version.rb
98
+ - lib/zweifische/zero_padding.rb
99
+ - zweifische.gemspec
100
+ homepage: https://github.com/fudanchii/twofish
101
+ licenses: []
102
+ metadata: {}
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 2.6.14
120
+ signing_key:
121
+ specification_version: 4
122
+ summary: Ruby binding for @drewcsillag twofish implementation
123
+ test_files: []