Class: Tem::Keys::Symmetric
Overview
Wraps a TEM symmetric key, e.g. an AES key.
Constant Summary
collapse
- @@cipher_mode =
'EDE-CBC'
- @@signature_mode =
'CBC'
Instance Attribute Summary
Attributes inherited from Tem::Key
#ssl_key
Class Method Summary
collapse
Instance Method Summary
collapse
Methods inherited from Tem::Key
new_from_ssl_key, #to_tem_key
Constructor Details
#initialize(ssl_key, raw_key = nil) ⇒ Symmetric
Creates a new symmetric key based on an OpenSSL Cipher instance, augmented with a key accessor.
Args:
ssl_key:: the OpenSSL key, or a string containing the raw key
raw_key:: if the OpenSSL key does not support calls to +key+, the raw key
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
# File 'lib/tem/keys/symmetric.rb', line 29
def initialize(ssl_key, raw_key = nil)
if ssl_key.kind_of? OpenSSL::Cipher
@key = raw_key || ssl_key.key
@cipher_class = ssl_key.class
else
@key = ssl_key
@cipher_class = OpenSSL::Cipher::DES
end
cipher = @cipher_class.new @@cipher_mode
class <<cipher
def key=(new_key)
super
@_key = new_key
end
def key
@_key
end
end
cipher.key = @key
cipher.iv = "\0" * 16
super cipher
end
|
Class Method Details
.generate ⇒ Object
Generates a new symmetric key.
17
18
19
20
21
|
# File 'lib/tem/keys/symmetric.rb', line 17
def self.generate
cipher = OpenSSL::Cipher::DES.new @@cipher_mode
key = cipher.random_key
self.new key
end
|
.new_from_array(array) ⇒ Object
121
122
123
124
125
126
127
128
129
|
# File 'lib/tem/keys/symmetric.rb', line 121
def self.new_from_array(array)
cipher_class = array[0].split('::').inject(Kernel) do |scope, name|
scope.const_get name
end
cipher = cipher_class.new @@cipher_mode
self.new cipher, array[1]
end
|
.new_from_yaml_str(yaml_str) ⇒ Object
131
132
133
134
|
# File 'lib/tem/keys/symmetric.rb', line 131
def self.new_from_yaml_str(yaml_str)
array = YAML.load yaml_str
new_from_array array
end
|
Instance Method Details
#decrypt(data) ⇒ Object
91
92
93
|
# File 'lib/tem/keys/symmetric.rb', line 91
def decrypt(data)
encrypt_or_decrypt data, false
end
|
#encrypt(data) ⇒ Object
87
88
89
|
# File 'lib/tem/keys/symmetric.rb', line 87
def encrypt(data)
encrypt_or_decrypt data, true
end
|
#encrypt_or_decrypt(data, do_encrypt) ⇒ Object
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
# File 'lib/tem/keys/symmetric.rb', line 56
def encrypt_or_decrypt(data, do_encrypt)
cipher = @cipher_class.new @@cipher_mode
do_encrypt ? cipher.encrypt : cipher.decrypt
cipher.key = @key
cipher.iv = "\0" * 16
cipher.padding = 0
pdata = data.respond_to?(:pack) ? data.pack('C*') : data
if do_encrypt
pdata << "\x80"
if pdata.length % cipher.block_size != 0
pdata << "\0" * (cipher.block_size - pdata.length % cipher.block_size)
end
end
result = cipher.update pdata
result += cipher.final
unless do_encrypt
result_length = result.length
loop do
result_length -= 1
next if result[result_length].ord == 0
raise "Invalid padding" unless result[result_length].ord == 0x80
break
end
result = result[0, result_length]
end
data.respond_to?(:pack) ? result.unpack('C*') : result
end
|
#sign(data) ⇒ Object
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
# File 'lib/tem/keys/symmetric.rb', line 95
def sign(data)
cipher = @cipher_class.new @@cipher_mode
cipher.encrypt
cipher.key = @key
cipher.iv = "\0" * 16
cipher.padding = 0
pdata = data.respond_to?(:pack) ? data.pack('C*') : data
pdata << "\x80"
if pdata.length % cipher.block_size != 0
pdata << "\0" * (cipher.block_size - pdata.length % cipher.block_size)
end
result = cipher.update pdata
result += cipher.final
result = result[-cipher.block_size, cipher.block_size]
data.respond_to?(:pack) ? result.unpack('C*') : result
end
|
#to_array ⇒ Object
136
137
138
|
# File 'lib/tem/keys/symmetric.rb', line 136
def to_array
[@cipher_class.name, @key]
end
|
#to_yaml_str ⇒ Object
140
141
142
|
# File 'lib/tem/keys/symmetric.rb', line 140
def to_yaml_str
self.to_array.to_yaml.to_s
end
|
#verify(data, signature) ⇒ Object
114
115
116
117
118
119
|
# File 'lib/tem/keys/symmetric.rb', line 114
def verify(data, signature)
hmac = sign(data)
hmac = hmac.pack('C*') if hmac.respond_to?(:pack)
signature = signature.pack('C*') if signature.respond_to?(:pack)
hmac == signature
end
|