security_client 0.1.0 → 0.1.5

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 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: