ig-crypto-utils 0.0.2
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.
- 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: []
|