security_client 0.1.0 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 055b4ebf4046542527af7b8df744c592ff0921a8e5d08af6f470e2e72c96c8c2
4
- data.tar.gz: 694fa499f049beaae0480892cb2b2bc0100f1e22fed3eb94ab80c250b026d1a0
3
+ metadata.gz: 25ec3c95ad9fa1853fed49499126461b7872bb04688a677239ec8c1ad6963e5a
4
+ data.tar.gz: 61975e25115a99c7be9469d08c2ab9543e2923fd9155e657973eee62dba4846a
5
5
  SHA512:
6
- metadata.gz: 0cb89ec2fca2a529d4a75c39505efcaefd6fd2b1716ec435cc206e56d7b7d03bd8f67b1437295c936147425d062afd6c0422ae5ba2854aefa4da31f01ff476e9
7
- data.tar.gz: 1e6dc6e527eb4d63796d96f000f37245d5b83cf19a7eb9d72c26c955a797099889138d7f1178492a012ba4a5a9915188b58ccfdfda8db09ccb1ea810a94ff7c1
6
+ metadata.gz: 371bddc6ede995b027bc0f4933b7352a660ed74875f9bbd5b3059cc65c728fdf5935ea6667c203e78f8f4f5602e3c5ea840eb6bcb881fd5f9226627d4a628f48
7
+ data.tar.gz: 92a9a1a0951cf8c78082795fd597817bc9e46f6f35d2d47a2fa715e2ab3c189fd4e3771aba5d825b261c6fc4d0cc03086929d8f5c64eac6304ddd36ffba82096
data/README.md CHANGED
@@ -22,7 +22,67 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
25
+ ```ruby
26
+ # Initialize the Client
27
+ client = SecurityClient::Voltron.new(
28
+ access_key_id: 'Your access key',
29
+ secret_signing_key: 'Your secret signing key',
30
+ secret_crypto_access_key: 'Your secret crypto access key',
31
+ host: 'Your host'
32
+ )
33
+
34
+ # Simple Encryption
35
+ encrypted_result = client.encrypt(
36
+ uses: 'Key Uses',
37
+ data: 'Data to be encrypted'
38
+ )
39
+
40
+ # Simple Decryption
41
+ original_data = client.decrypt(
42
+ data: 'Encrypted Data'
43
+ )
44
+
45
+ # Piecewise Encryption
46
+ # Get your credentials ready
47
+ credentials = OpenStruct.new(
48
+ access_key_id: 'Your access key',
49
+ secret_signing_key: 'Your secret signing key',
50
+ secret_crypto_access_key: 'Your secret crypto access key',
51
+ host: 'Your host'
52
+ )
53
+
54
+ # Build the encryption object
55
+ enc = SecurityClient::Encryption.new(credentials, uses)
56
+ # Begin the encryption
57
+ enc.begin()
58
+ # Update the cipher with the raw data, can be supplied directly or in chunks
59
+ enc.update(data)
60
+ # End the encryption
61
+ enc.end()
62
+ # Reset the encryption object to initial state and cleanup the memory in use
63
+ enc.close()
64
+
65
+ # Piecewise Decryption
66
+ # Get your credentials ready
67
+ credentials = OpenStruct.new(
68
+ access_key_id: 'Your access key',
69
+ secret_signing_key: 'Your secret signing key',
70
+ secret_crypto_access_key: 'Your secret crypto access key',
71
+ host: 'Your host'
72
+ )
73
+
74
+ # Build the decryption object
75
+ dec = SecurityClient::Decryption.new(credentials)
76
+ # Begin the decryption
77
+ dec.begin()
78
+ # Update the cipher with the raw data, can be supplied directly or in chunks
79
+ dec.update(data)
80
+ # End the decryption
81
+ dec.end()
82
+ # Reset the decryption object to initial state and cleanup the memory in use
83
+ dec.close()
84
+
85
+ ```
26
86
 
27
87
  ## Development
28
88
 
@@ -28,7 +28,6 @@ module SecurityClient
28
28
  enc.close() if enc
29
29
  raise
30
30
  end
31
- puts res
32
31
  return res
33
32
  end
34
33
 
@@ -42,7 +41,6 @@ module SecurityClient
42
41
  dec.close() if dec
43
42
  raise
44
43
  end
45
- puts res
46
44
  return res
47
45
  end
48
46
 
@@ -335,7 +333,7 @@ class SecurityClient::Decryption
335
333
  # Initialize the decryption module object
336
334
  # Set the credentials in instance varibales to be used among methods
337
335
  # the server to which to make the request
338
- raise RuntimeError, 'Some of your credentials are missing, please check!' if !validate_creds(creds)
336
+ # raise RuntimeError, 'Some of your credentials are missing, please check!' if !validate_creds(creds)
339
337
  @host = creds.host.blank? ? VOLTRON_HOST : creds.host
340
338
 
341
339
  # The client's public API key (used to identify the client to the server
@@ -350,194 +348,192 @@ class SecurityClient::Decryption
350
348
  @decryption_ready = true
351
349
  @decryption_started = false
352
350
 
353
- end
351
+ end
354
352
 
355
- def endpoint_base
356
- @host + '/api/v0'
357
- end
353
+ def endpoint_base
354
+ @host + '/api/v0'
355
+ end
358
356
 
359
- def endpoint
360
- '/api/v0/decryption/key'
361
- end
357
+ def endpoint
358
+ '/api/v0/decryption/key'
359
+ end
362
360
 
363
- def begin
364
- # Begin the decryption process
361
+ def begin
362
+ # Begin the decryption process
365
363
 
366
- # This interface does not take any cipher text in its arguments
367
- # in an attempt to maintain an API that corresponds to the
368
- # encryption object. In doing so, the work that can take place
369
- # in this function is limited. without any data, there is no
370
- # way to determine which key is in use or decrypt any data.
371
- #
372
- # this function simply throws an error if starting an decryption
373
- # while one is already in progress, and initializes the internal
374
- # buffer
364
+ # This interface does not take any cipher text in its arguments
365
+ # in an attempt to maintain an API that corresponds to the
366
+ # encryption object. In doing so, the work that can take place
367
+ # in this function is limited. without any data, there is no
368
+ # way to determine which key is in use or decrypt any data.
369
+ #
370
+ # this function simply throws an error if starting an decryption
371
+ # while one is already in progress, and initializes the internal
372
+ # buffer
375
373
 
376
- raise RuntimeError, 'Decryption is not ready' if !@decryption_ready
374
+ raise RuntimeError, 'Decryption is not ready' if !@decryption_ready
377
375
 
378
- raise RuntimeError, 'Decryption Already Started' if @decryption_started
376
+ raise RuntimeError, 'Decryption Already Started' if @decryption_started
379
377
 
380
- raise RuntimeError, 'Decryption already in progress' if @key.present? and @key.key?("dec")
381
- @decryption_started = true
382
- @data = ''
383
- end
378
+ raise RuntimeError, 'Decryption already in progress' if @key.present? and @key.key?("dec")
379
+ @decryption_started = true
380
+ @data = ''
381
+ end
384
382
 
385
- def update(data)
386
- # Decryption of cipher text is performed here
387
- # Cipher text must be passed to this function in the order in which it was output from the encryption.update function.
388
-
389
- # Each encryption has a header on it that identifies the algorithm
390
- # used and an encryption of the data key that was used to encrypt
391
- # the original plain text. there is no guarantee how much of that
392
- # data will be passed to this function or how many times this
393
- # function will be called to process all of the data. to that end,
394
- # this function buffers data internally, when it is unable to
395
- # process it.
396
- #
397
- # The function buffers data internally until the entire header is
398
- # received. once the header has been received, the encrypted data
399
- # key is sent to the server for decryption. after the header has
400
- # been successfully handled, this function always decrypts all of
401
- # the data in its internal buffer *except* for however many bytes
402
- # are specified by the algorithm's tag size. see the end() function
403
- # for details.
404
-
405
- raise RuntimeError, 'Decryption is not Started' if !@decryption_started
406
-
407
- # Append the incoming data in the internal data buffer
408
- @data = @data + data
409
-
410
- # if there is no key or 'dec' member of key, then the code is still trying to build a complete header
411
- if !@key.present? or !@key.key?("dec")
412
- struct_length = [1,1,1,1,1].pack('CCCCn').length
413
- packed_struct = @data[0...struct_length]
414
-
415
- # Does the buffer contain enough of the header to
416
- # determine the lengths of the initialization vector
417
- # and the key?
418
- if @data.length > struct_length
419
- # Unpack the values packed in encryption
420
- version, flag_for_later, algorithm_id, iv_length, key_length = packed_struct.unpack('CCCCn')
421
-
422
- # verify flag and version are 0
423
- raise RuntimeError, 'invalid encryption header' if version != 0 or flag_for_later != 0
424
-
425
- # Does the buffer contain the entire header?
426
- if @data.length > struct_length + iv_length + key_length
427
- # Extract the initialization vector
428
- iv = @data[struct_length...iv_length + struct_length]
429
- # Extract the encryped key
430
- encrypted_key = @data[struct_length + iv_length...key_length + struct_length + iv_length]
431
- # Remove the header from the buffer
432
- @data = @data[struct_length + iv_length + key_length..-1]
433
-
434
- # generate a local identifier for the key
435
- hash_sha512 = OpenSSL::Digest::SHA512.new
436
- hash_sha512 << encrypted_key
437
- client_id = hash_sha512.digest
438
-
439
- if @key.present?
440
- if @key['client_id'] != client_id
441
- close()
383
+ def update(data)
384
+ # Decryption of cipher text is performed here
385
+ # Cipher text must be passed to this function in the order in which it was output from the encryption.update function.
386
+
387
+ # Each encryption has a header on it that identifies the algorithm
388
+ # used and an encryption of the data key that was used to encrypt
389
+ # the original plain text. there is no guarantee how much of that
390
+ # data will be passed to this function or how many times this
391
+ # function will be called to process all of the data. to that end,
392
+ # this function buffers data internally, when it is unable to
393
+ # process it.
394
+ #
395
+ # The function buffers data internally until the entire header is
396
+ # received. once the header has been received, the encrypted data
397
+ # key is sent to the server for decryption. after the header has
398
+ # been successfully handled, this function always decrypts all of
399
+ # the data in its internal buffer *except* for however many bytes
400
+ # are specified by the algorithm's tag size. see the end() function
401
+ # for details.
402
+
403
+ raise RuntimeError, 'Decryption is not Started' if !@decryption_started
404
+
405
+ # Append the incoming data in the internal data buffer
406
+ @data = @data + data
407
+
408
+ # if there is no key or 'dec' member of key, then the code is still trying to build a complete header
409
+ if !@key.present? or !@key.key?("dec")
410
+ struct_length = [1,1,1,1,1].pack('CCCCn').length
411
+ packed_struct = @data[0...struct_length]
412
+
413
+ # Does the buffer contain enough of the header to
414
+ # determine the lengths of the initialization vector
415
+ # and the key?
416
+ if @data.length > struct_length
417
+ # Unpack the values packed in encryption
418
+ version, flag_for_later, algorithm_id, iv_length, key_length = packed_struct.unpack('CCCCn')
419
+
420
+ # verify flag and version are 0
421
+ raise RuntimeError, 'invalid encryption header' if version != 0 or flag_for_later != 0
422
+
423
+ # Does the buffer contain the entire header?
424
+ if @data.length > struct_length + iv_length + key_length
425
+ # Extract the initialization vector
426
+ iv = @data[struct_length...iv_length + struct_length]
427
+ # Extract the encryped key
428
+ encrypted_key = @data[struct_length + iv_length...key_length + struct_length + iv_length]
429
+ # Remove the header from the buffer
430
+ @data = @data[struct_length + iv_length + key_length..-1]
431
+
432
+ # generate a local identifier for the key
433
+ hash_sha512 = OpenSSL::Digest::SHA512.new
434
+ hash_sha512 << encrypted_key
435
+ client_id = hash_sha512.digest
436
+
437
+ if @key.present?
438
+ if @key['client_id'] != client_id
439
+ close()
440
+ end
442
441
  end
443
- end
444
442
 
445
- # IF key object not exists, request a new one from the server
446
- if !@key.present?
447
- url = endpoint_base + "/decryption/key"
448
- query = {encrypted_data_key: Base64.strict_encode64(encrypted_key)}
449
- headers = Auth.build_headers(@papi, @sapi, endpoint, query, @host, 'post')
450
-
451
- response = HTTParty.post(
452
- url,
453
- body: query.to_json,
454
- headers: headers
455
- )
456
-
457
- # Response status is 200 OK
458
- if response.code == WEBrick::HTTPStatus::RC_OK
459
- @key = {}
460
- @key['finger_print'] = response['key_fingerprint']
461
- @key['client_id'] = client_id
462
- @key['session'] = response['encryption_session']
463
-
464
- @key['algorithm'] = 'aes-256-gcm'
465
-
466
- encrypted_private_key = response['encrypted_private_key']
467
- # Decrypt the encryped private key using SRSA
468
- private_key = OpenSSL::PKey::RSA.new(encrypted_private_key,@srsa)
469
-
470
- wrapped_data_key = response['wrapped_data_key']
471
- # Decode WDK from base64 format
472
- wdk = Base64.strict_decode64(wrapped_data_key)
473
- # Use private key to decrypt the wrapped data key
474
- dk = private_key.private_decrypt(wdk,OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
475
-
476
- @key['raw'] = dk
477
- @key['uses'] = 0
478
- else
479
- # Raise the error if response is not 200
480
- raise RuntimeError, "HTTPError Response: Expected 201, got #{response.code}"
443
+ # IF key object not exists, request a new one from the server
444
+ if !@key.present?
445
+ url = endpoint_base + "/decryption/key"
446
+ query = {encrypted_data_key: Base64.strict_encode64(encrypted_key)}
447
+ headers = Auth.build_headers(@papi, @sapi, endpoint, query, @host, 'post')
448
+
449
+ response = HTTParty.post(
450
+ url,
451
+ body: query.to_json,
452
+ headers: headers
453
+ )
454
+
455
+ # Response status is 200 OK
456
+ if response.code == WEBrick::HTTPStatus::RC_OK
457
+ @key = {}
458
+ @key['finger_print'] = response['key_fingerprint']
459
+ @key['client_id'] = client_id
460
+ @key['session'] = response['encryption_session']
461
+
462
+ @key['algorithm'] = 'aes-256-gcm'
463
+
464
+ encrypted_private_key = response['encrypted_private_key']
465
+ # Decrypt the encryped private key using SRSA
466
+ private_key = OpenSSL::PKey::RSA.new(encrypted_private_key,@srsa)
467
+
468
+ wrapped_data_key = response['wrapped_data_key']
469
+ # Decode WDK from base64 format
470
+ wdk = Base64.strict_decode64(wrapped_data_key)
471
+ # Use private key to decrypt the wrapped data key
472
+ dk = private_key.private_decrypt(wdk,OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
473
+
474
+ @key['raw'] = dk
475
+ @key['uses'] = 0
476
+ else
477
+ # Raise the error if response is not 200
478
+ raise RuntimeError, "HTTPError Response: Expected 201, got #{response.code}"
479
+ end
481
480
  end
482
- end
483
481
 
484
- # If the key object exists, create a new decryptor
485
- # with the initialization vector from the header and
486
- # the decrypted key (which is either new from the
487
- # server or cached from the previous decryption). in
488
- # either case, increment the key usage
482
+ # If the key object exists, create a new decryptor
483
+ # with the initialization vector from the header and
484
+ # the decrypted key (which is either new from the
485
+ # server or cached from the previous decryption). in
486
+ # either case, increment the key usage
489
487
 
490
- if @key.present?
491
- @algo = Algo.new.get_algo(@key['algorithm'])
492
- @key['dec'] = Algo.new.decryptor(@algo, @key['raw'], iv)
493
- @key['uses'] += 1
488
+ if @key.present?
489
+ @algo = Algo.new.get_algo(@key['algorithm'])
490
+ @key['dec'] = Algo.new.decryptor(@algo, @key['raw'], iv)
491
+ @key['uses'] += 1
492
+ end
494
493
  end
495
494
  end
496
495
  end
497
- end
498
496
 
499
- # if the object has a key and a decryptor, then decrypt whatever
500
- # data is in the buffer, less any data that needs to be saved to
501
- # serve as the tag.
502
- plain_text = ''
503
- if @key.present? and @key.key?("dec")
504
- size = @data.length - @algo[:tag_length]
505
- if size > 0
506
- puts @data[0..size-1]
507
-
508
- plain_text = @key['dec'].update(@data[0..size-1])
509
- @data = @data[size..-1]
497
+ # if the object has a key and a decryptor, then decrypt whatever
498
+ # data is in the buffer, less any data that needs to be saved to
499
+ # serve as the tag.
500
+ plain_text = ''
501
+ if @key.present? and @key.key?("dec")
502
+ size = @data.length - @algo[:tag_length]
503
+ if size > 0
504
+ plain_text = @key['dec'].update(@data[0..size-1])
505
+ @data = @data[size..-1]
506
+ end
507
+ return plain_text
510
508
  end
511
- return plain_text
512
- end
513
509
 
514
- end
510
+ end
515
511
 
516
- def end
517
- raise RuntimeError, 'Decryption is not Started' if !@decryption_started
518
- # The update function always maintains tag-size bytes in
519
- # the buffer because this function provides no data parameter.
520
- # by the time the caller calls this function, all data must
521
- # have already been input to the decryption object.
512
+ def end
513
+ raise RuntimeError, 'Decryption is not Started' if !@decryption_started
514
+ # The update function always maintains tag-size bytes in
515
+ # the buffer because this function provides no data parameter.
516
+ # by the time the caller calls this function, all data must
517
+ # have already been input to the decryption object.
522
518
 
523
- sz = @data.length - @algo[:tag_length]
519
+ sz = @data.length - @algo[:tag_length]
524
520
 
525
- raise RuntimeError, 'Invalid Tag!' if sz < 0
526
- if sz == 0
527
- @key['dec'].auth_tag = @data
528
- begin
529
- pt = @key['dec'].final
530
- # Delete the decryptor context
531
- @key.delete('dec')
532
- # Return the decrypted plain data
533
- @decryption_started = false
534
- return pt
535
- rescue Exception => e
536
- print 'Invalid cipher data or tag!'
537
- return ''
521
+ raise RuntimeError, 'Invalid Tag!' if sz < 0
522
+ if sz == 0
523
+ @key['dec'].auth_tag = @data
524
+ begin
525
+ pt = @key['dec'].final
526
+ # Delete the decryptor context
527
+ @key.delete('dec')
528
+ # Return the decrypted plain data
529
+ @decryption_started = false
530
+ return pt
531
+ rescue Exception => e
532
+ print 'Invalid cipher data or tag!'
533
+ return ''
534
+ end
538
535
  end
539
536
  end
540
- end
541
537
 
542
538
  def close
543
539
  raise RuntimeError, 'Decryption currently running' if @decryption_started
@@ -1,3 +1,3 @@
1
1
  module SecurityClient
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.5"
3
3
  end
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.email = ["vinay.ymca@gmail.com"]
10
10
 
11
11
  spec.summary = %q{Ubiq Security ruby client}
12
-
12
+ spec.homepage = "https://github.com/vinaymehta/security_client"
13
13
  # Specify which files should be added to the gem when it is released.
14
14
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
15
15
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: security_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - vinaymehta
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-18 00:00:00.000000000 Z
11
+ date: 2020-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -70,7 +70,7 @@ files:
70
70
  - lib/security_client.rb
71
71
  - lib/security_client/version.rb
72
72
  - security_client.gemspec
73
- homepage:
73
+ homepage: https://github.com/vinaymehta/security_client
74
74
  licenses: []
75
75
  metadata: {}
76
76
  post_install_message: