ig-crypto-utils 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ig-crypto-utils.gemspec +16 -0
- data/lib/ig-crypto-utils.rb +142 -0
- data/tests/aes_tests.rb +27 -0
- data/tests/ecdsa_tests.rb +36 -0
- metadata +47 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ec754385ef30a08d89b3c0b866245b404a50868a
|
4
|
+
data.tar.gz: 369c33e30159d8e254ae73dbe447d359c6eb7f2a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 727072d7053adf71cce4fbd9bab32a2ac3b99145fe5f31b203a45aa3d817adbd700b3618f5896a09e9fb8cd201e622043667ff377fa5975de62c53cac5772578
|
7
|
+
data.tar.gz: dac2ad1dd4a0159bc10410d945a570220db8e145b528b1e2bb3793f260b6b32043a59c8bc4e72ec587b8b41cdd25580915e12a0eba8e3eb319e63539380ce51d
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'ig-crypto-utils'
|
3
|
+
s.version = '0.0.2'
|
4
|
+
s.date = '2015-04-17'
|
5
|
+
s.summary = 'AES and EDCSA utils based on OpenSSL'
|
6
|
+
s.description = 'Asymmetric/symmetric encryption utility'
|
7
|
+
s.authors = ['Infinity-G']
|
8
|
+
s.email = 'developer@infinity-g.com'
|
9
|
+
s.files = `git ls-files`.split("\n")
|
10
|
+
s.require_paths = ["lib"]
|
11
|
+
s.homepage = ''
|
12
|
+
s.license = 'MIT'
|
13
|
+
end
|
14
|
+
|
15
|
+
# run 'gem build ig-crypto-utils' to create gem
|
16
|
+
# run
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'digest'
|
3
|
+
require 'base64'
|
4
|
+
require 'openssl'
|
5
|
+
|
6
|
+
# NOTE: All inputs of methods in this module require Base64 encoding!
|
7
|
+
# Outputs are all Base64 encoded
|
8
|
+
|
9
|
+
module CryptoUtils
|
10
|
+
|
11
|
+
# General use static functions
|
12
|
+
|
13
|
+
def self.encode_base64(value)
|
14
|
+
unless value =~ /^([A-Za-z0-9+]{4})*([A-Za-z0-9+]{4}|[A-Za-z0-9+]{3}=|[A-Za-z0-9+]{2}==)$/i
|
15
|
+
puts "#{value} is NOT base64 encoded, ENCODING..."
|
16
|
+
return Base64.encode64 value
|
17
|
+
end
|
18
|
+
|
19
|
+
value
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.decode_base64(value)
|
23
|
+
if value =~ /^([A-Za-z0-9+]{4})*([A-Za-z0-9+]{4}|[A-Za-z0-9+]{3}=|[A-Za-z0-9+]{2}==)$/i
|
24
|
+
puts "#{value} is base64 encoded, ...DECODING"
|
25
|
+
return Base64.decode64 value
|
26
|
+
end
|
27
|
+
|
28
|
+
value
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.create_digest(value)
|
32
|
+
Digest::SHA2.base64digest value
|
33
|
+
end
|
34
|
+
|
35
|
+
#############################
|
36
|
+
# SYMMETRIC ENCRYPTION UTIL
|
37
|
+
#############################
|
38
|
+
|
39
|
+
class AesUtil
|
40
|
+
# https://gist.github.com/byu/99651
|
41
|
+
# http://ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/Cipher.html
|
42
|
+
|
43
|
+
def encrypt(encoded_plain_text, encoded_key)
|
44
|
+
|
45
|
+
cipher = OpenSSL::Cipher::AES.new(256, :CBC) # CBC = cipher block chaining
|
46
|
+
cipher.encrypt
|
47
|
+
|
48
|
+
# generate a random iv
|
49
|
+
iv = cipher.random_iv
|
50
|
+
|
51
|
+
cipher.key = encoded_key
|
52
|
+
cipher.iv = iv
|
53
|
+
|
54
|
+
result = cipher.update(encoded_plain_text) + cipher.final
|
55
|
+
|
56
|
+
encoded_result = Base64.encode64 result
|
57
|
+
encoded_iv = Base64.encode64 iv
|
58
|
+
|
59
|
+
{:cipher_text => encoded_result, :iv => encoded_iv}
|
60
|
+
end
|
61
|
+
|
62
|
+
def decrypt(encoded_cipher_text, encoded_key, encoded_iv)
|
63
|
+
|
64
|
+
decoded_cipher_text = Base64.decode64 encoded_cipher_text
|
65
|
+
decoded_iv = Base64.decode64 encoded_iv
|
66
|
+
|
67
|
+
cipher = OpenSSL::Cipher::AES.new(256, :CBC)
|
68
|
+
cipher.decrypt
|
69
|
+
|
70
|
+
cipher.key = encoded_key
|
71
|
+
cipher.iv = decoded_iv
|
72
|
+
|
73
|
+
cipher.update(decoded_cipher_text) + cipher.final
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
##########################
|
79
|
+
# ASYMMETRIC SIGNING UTIL
|
80
|
+
##########################
|
81
|
+
|
82
|
+
class EcdsaUtil
|
83
|
+
|
84
|
+
# for a 256-bit ECDSA curve, the uncompressed pubkey is 512 bits (256 bits of x, 256 bits of y, no sign bit).
|
85
|
+
# The compressed pubkey is 257 bits (256 bits of x, one bit of the sign of y).
|
86
|
+
def create_key_pair
|
87
|
+
group_name = 'secp256k1'
|
88
|
+
|
89
|
+
# set compression to true for key generation on the group
|
90
|
+
group = OpenSSL::PKey::EC::Group.new(group_name)
|
91
|
+
group.point_conversion_form = :compressed
|
92
|
+
|
93
|
+
# instantiate the curve and generate the keys
|
94
|
+
curve = OpenSSL::PKey::EC.new(group)
|
95
|
+
curve.generate_key
|
96
|
+
|
97
|
+
public_key = curve.public_key
|
98
|
+
private_key = curve.private_key
|
99
|
+
|
100
|
+
# get binary representation of keys
|
101
|
+
pk_bn_bin = public_key.to_bn.to_s(2)
|
102
|
+
sk_bn_bin = private_key.to_s(2)
|
103
|
+
|
104
|
+
#base64 encode keys
|
105
|
+
encoded_pk = Base64.encode64(pk_bn_bin)
|
106
|
+
encoded_sk = Base64.encode64(sk_bn_bin)
|
107
|
+
|
108
|
+
{:pk => encoded_pk, :sk => encoded_sk}
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
def sign(encoded_data, encoded_private_key)
|
113
|
+
group_name = 'secp256k1'
|
114
|
+
|
115
|
+
decoded_data = Base64.decode64 encoded_data
|
116
|
+
decoded_private_key = Base64.decode64 encoded_private_key
|
117
|
+
|
118
|
+
curve = OpenSSL::PKey::EC.new(group_name)
|
119
|
+
curve.private_key = OpenSSL::BN.new(decoded_private_key, 2)
|
120
|
+
|
121
|
+
result = curve.dsa_sign_asn1 decoded_data
|
122
|
+
|
123
|
+
Base64.encode64 result
|
124
|
+
end
|
125
|
+
|
126
|
+
def validate_signature(encoded_digest, encoded_signature, encoded_public_key)
|
127
|
+
group_name = 'secp256k1'
|
128
|
+
|
129
|
+
decoded_signature = Base64.decode64 encoded_signature
|
130
|
+
decoded_digest = Base64.decode64 encoded_digest
|
131
|
+
decoded_public_key = Base64.decode64 encoded_public_key
|
132
|
+
|
133
|
+
curve = OpenSSL::PKey::EC.new(group_name)
|
134
|
+
key_bn = OpenSSL::BN.new(decoded_public_key, 2)
|
135
|
+
group = OpenSSL::PKey::EC::Group.new(group_name)
|
136
|
+
curve.public_key = OpenSSL::PKey::EC::Point.new(group, key_bn)
|
137
|
+
|
138
|
+
curve.dsa_verify_asn1(decoded_digest, decoded_signature)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
data/tests/aes_tests.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'minitest'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
require_relative '../../ig-crypto-utils/lib/ig-crypto-utils'
|
6
|
+
|
7
|
+
class AesTests < MiniTest::Test
|
8
|
+
|
9
|
+
def test_encrypt
|
10
|
+
# NOTE: AesUtil methods expect all inputs to be Base64 encoded
|
11
|
+
|
12
|
+
util = CryptoUtils::AesUtil.new
|
13
|
+
|
14
|
+
plain_text = '{"blah":"Super secret text"}'
|
15
|
+
encoded_plain_text = Base64.encode64 plain_text
|
16
|
+
|
17
|
+
aes_256_key = 'ky4xgi0+KvLYmVp1J5akqkJkv8z5rJsHTo9FcBc0hgo=' # already base64 encoded
|
18
|
+
|
19
|
+
# encrypt
|
20
|
+
encrypted_result = util.encrypt encoded_plain_text, aes_256_key
|
21
|
+
|
22
|
+
# decrypt
|
23
|
+
decrypted_result = util.decrypt encrypted_result[:cipher_text], aes_256_key, encrypted_result[:iv]
|
24
|
+
|
25
|
+
assert decrypted_result == encoded_plain_text
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'minitest'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
require_relative '../../ig-crypto-utils/lib/ig-crypto-utils'
|
6
|
+
|
7
|
+
class EcdsaTests < MiniTest::Test
|
8
|
+
|
9
|
+
def test_create_key_pair
|
10
|
+
result = CryptoUtils::EcdsaUtil.new.create_key_pair
|
11
|
+
|
12
|
+
assert result[:pk]!= nil
|
13
|
+
assert result[:sk]!= nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_sign
|
17
|
+
text = 'Text to sign'
|
18
|
+
text_digest = CryptoUtils.create_digest text
|
19
|
+
encoded_text_digest = Base64.encode64 text_digest
|
20
|
+
|
21
|
+
encoded_secret_key = 'gCrHtl8VVWs6EuJLy7vPqVdBZWzRAR9ZCjIRRpoWvME=' # already base64 encoded
|
22
|
+
encoded_public_key = 'Ag7PunGy2BmnAi+PGE4/Dm9nCg1URv8wLZwSOggyfmAn' # already base64 encoded
|
23
|
+
|
24
|
+
util = CryptoUtils::EcdsaUtil.new
|
25
|
+
|
26
|
+
# sign
|
27
|
+
encoded_result = util.sign encoded_text_digest, encoded_secret_key
|
28
|
+
|
29
|
+
# validate
|
30
|
+
validation_result = util.validate_signature encoded_text_digest, encoded_result, encoded_public_key
|
31
|
+
|
32
|
+
puts validation_result
|
33
|
+
assert validation_result
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ig-crypto-utils
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Infinity-G
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-17 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Asymmetric/symmetric encryption utility
|
14
|
+
email: developer@infinity-g.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- ig-crypto-utils.gemspec
|
20
|
+
- lib/ig-crypto-utils.rb
|
21
|
+
- tests/aes_tests.rb
|
22
|
+
- tests/ecdsa_tests.rb
|
23
|
+
homepage: ''
|
24
|
+
licenses:
|
25
|
+
- MIT
|
26
|
+
metadata: {}
|
27
|
+
post_install_message:
|
28
|
+
rdoc_options: []
|
29
|
+
require_paths:
|
30
|
+
- lib
|
31
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - '>='
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
requirements: []
|
42
|
+
rubyforge_project:
|
43
|
+
rubygems_version: 2.4.2
|
44
|
+
signing_key:
|
45
|
+
specification_version: 4
|
46
|
+
summary: AES and EDCSA utils based on OpenSSL
|
47
|
+
test_files: []
|