openssl-cmac 1.0.0

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 (2) hide show
  1. data/lib/openssl_cmac.rb +69 -0
  2. metadata +46 -0
@@ -0,0 +1,69 @@
1
+ # This is an implementation of AES-CMAC Algorithm:
2
+ # http://tools.ietf.org/html/rfc4493
3
+ #
4
+ # OpenSSL version > 1.0.1 already has a native implementation of CMAC
5
+ # but there are no corresponding bindings in Ruby OpenSSL standard library
6
+
7
+ require 'openssl'
8
+
9
+ module OpenSSL
10
+ class CMAC
11
+ CONST_ZERO = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".force_encoding('ASCII-8BIT')
12
+ CONST_RB = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x87]
13
+
14
+ # key - base 128 bit AES key
15
+ def initialize(key)
16
+ @key = key
17
+ @k1, @k2 = CMAC.gen_subkeys(@key)
18
+ end
19
+
20
+ def generate(data)
21
+ data8 = data.dup.force_encoding('ASCII-8BIT')
22
+
23
+ xor_key = @k1
24
+ unless data8.size > 0 && 0 == data8.size % 16
25
+ xor_key = @k2
26
+ padding = "\x80"
27
+ padding << "\x00" * (15 - data8.size % 16)
28
+ data8 << padding
29
+ end
30
+
31
+ data8[-16, 16].unpack('C*').each_with_index do |e, i|
32
+ data8[data8.size - 16 + i] = (e ^ xor_key[i]).chr
33
+ end
34
+
35
+ cipher = Cipher::AES.new(128, :CBC)
36
+ cipher.encrypt
37
+ cipher.key = @key
38
+
39
+ cipher.update(data8)[-16, 16]
40
+ end
41
+
42
+ def verify(data, cmac)
43
+ generate(data) == cmac
44
+ end
45
+
46
+ def self.gen_subkeys(key)
47
+ cipher = Cipher::AES.new(128, :ECB)
48
+ cipher.encrypt
49
+ cipher.key = key
50
+
51
+ k1 = (cipher.update(CONST_ZERO)).unpack('C*')
52
+ xor_flag = k1[0] >= 0x80
53
+
54
+ k2 = Array.new(16)
55
+
56
+ k1.each_with_index {|e, i|
57
+ lsb = i == 15 ? 0 : (k1[i+1] & 0x80) / 0x80
58
+ k1[i] = (k1[i] << 1) % 256 | lsb
59
+ k1[i] ^= CONST_RB[i] if xor_flag
60
+
61
+ lsb = i == 15 ? 0 : (k1[i+1] << 1 & 0x80) / 0x80
62
+ k2[i] = (k1[i] << 1) % 256 | lsb
63
+ k2[i] ^= CONST_RB[i] if k1[0] >= 0x80
64
+ }
65
+
66
+ [k1, k2]
67
+ end
68
+ end
69
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: openssl-cmac
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Maxim M. Chechel
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-03-04 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: http://tools.ietf.org/html/rfc4493
15
+ email: maximchick@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/openssl_cmac.rb
21
+ homepage: https://github.com/maximchick/openssl-cmac
22
+ licenses:
23
+ - MIT
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubyforge_project:
42
+ rubygems_version: 1.8.25
43
+ signing_key:
44
+ specification_version: 3
45
+ summary: AES-CMAC algorithm implementation
46
+ test_files: []