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.
- data/lib/openssl_cmac.rb +69 -0
- metadata +46 -0
data/lib/openssl_cmac.rb
ADDED
@@ -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: []
|