ccrypto-java 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.java-version +1 -1
  3. data/.release_history.yml +4 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +1 -1
  6. data/Gemfile.lock +68 -53
  7. data/Rakefile +2 -1
  8. data/bin/console +14 -0
  9. data/jars/bcjmail-jdk18on-172.jar +0 -0
  10. data/jars/bcmail-jdk18on-172.jar +0 -0
  11. data/jars/bcpg-jdk18on-172.1.jar +0 -0
  12. data/jars/bcpkix-jdk18on-172.jar +0 -0
  13. data/jars/bcprov-ext-jdk18on-172.jar +0 -0
  14. data/jars/bcprov-jdk18on-172.jar +0 -0
  15. data/jars/bctls-jdk18on-172.jar +0 -0
  16. data/jars/bcutil-jdk18on-172.jar +0 -0
  17. data/lib/ccrypto/java/bc_const_mapping.rb +42 -0
  18. data/lib/ccrypto/java/data_conversion.rb +23 -2
  19. data/lib/ccrypto/java/engines/argon2_engine.rb +95 -0
  20. data/lib/ccrypto/java/engines/asn1_engine.rb +2 -1
  21. data/lib/ccrypto/java/engines/bcrypt_engine.rb +56 -0
  22. data/lib/ccrypto/java/engines/cipher_engine.rb +462 -130
  23. data/lib/ccrypto/java/engines/compression_engine.rb +7 -28
  24. data/lib/ccrypto/java/engines/crystal_dilithium_engine.rb +226 -0
  25. data/lib/ccrypto/java/engines/crystal_kyber_engine.rb +260 -0
  26. data/lib/ccrypto/java/engines/decompression_engine.rb +5 -4
  27. data/lib/ccrypto/java/engines/digest_engine.rb +221 -139
  28. data/lib/ccrypto/java/engines/ecc_engine.rb +249 -96
  29. data/lib/ccrypto/java/engines/ed25519_engine.rb +211 -0
  30. data/lib/ccrypto/java/engines/hkdf_engine.rb +82 -23
  31. data/lib/ccrypto/java/engines/hmac_engine.rb +98 -23
  32. data/lib/ccrypto/java/engines/pbkdf2_engine.rb +82 -33
  33. data/lib/ccrypto/java/engines/pkcs7_engine.rb +44 -33
  34. data/lib/ccrypto/java/engines/rsa_engine.rb +85 -31
  35. data/lib/ccrypto/java/engines/scrypt_engine.rb +12 -3
  36. data/lib/ccrypto/java/engines/secret_key_engine.rb +77 -12
  37. data/lib/ccrypto/java/engines/secret_sharing_engine.rb +17 -2
  38. data/lib/ccrypto/java/engines/x25519_engine.rb +249 -0
  39. data/lib/ccrypto/java/engines/x509_csr_engine.rb +141 -0
  40. data/lib/ccrypto/java/engines/x509_engine.rb +365 -71
  41. data/lib/ccrypto/java/ext/secret_key.rb +37 -25
  42. data/lib/ccrypto/java/ext/x509_cert.rb +429 -5
  43. data/lib/ccrypto/java/ext/x509_csr.rb +151 -0
  44. data/lib/ccrypto/java/jce_provider.rb +0 -11
  45. data/lib/ccrypto/java/keystore/jce_keystore.rb +205 -0
  46. data/lib/ccrypto/java/keystore/jks_keystore.rb +52 -0
  47. data/lib/ccrypto/java/keystore/keystore.rb +97 -0
  48. data/lib/ccrypto/java/keystore/pem_keystore.rb +147 -0
  49. data/lib/ccrypto/java/keystore/pkcs12_keystore.rb +56 -0
  50. data/lib/ccrypto/java/utils/comparator.rb +25 -2
  51. data/lib/ccrypto/java/version.rb +1 -1
  52. data/lib/ccrypto/java.rb +46 -0
  53. data/lib/ccrypto/provider.rb +139 -3
  54. metadata +40 -24
  55. data/ccrypto-java.gemspec +0 -44
  56. data/jars/bcmail-jdk15on-165.jar +0 -0
  57. data/jars/bcpg-jdk15on-165.jar +0 -0
  58. data/jars/bcpkix-jdk15on-165.jar +0 -0
  59. data/jars/bcprov-ext-jdk15on-165.jar +0 -0
  60. data/jars/bcprov-jdk15on-165.jar +0 -0
  61. data/jars/bctls-jdk15on-165.jar +0 -0
  62. data/lib/ccrypto/java/keybundle_store/pkcs12.rb +0 -125
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6de516075322f46df8dc000fb1160c5719cc993b9ac3619e643eef54dfa4cf7c
4
- data.tar.gz: eca79e4bf92f9cefb090e5aaa06401774a19d4d194cff264cf939f2200b2a772
3
+ metadata.gz: 6c5ed78934fdba66ff0a488debee35a2ea956c51b031a6ed1ffa3bc2bb09d870
4
+ data.tar.gz: 31506e93209f940df76eb23b1539bf962a1ae63210d90c1665a99c61d250dd20
5
5
  SHA512:
6
- metadata.gz: 1e2d6bcefb3e2288526ccad521bcdaa01e959c3d4f336f8ce67c239f0f4fe6d958e95a6b601f8abc76a6ab3bf259d3ef2e94557d7d85195c68987609be83c298
7
- data.tar.gz: b74f70994b7828b6db115c242cc5e4daed1452b67d1d801620ee4f91e8566a593fdd10c5616eaf0e9911f4482fc65b692cb501473ae5e940710cda125700cb7c
6
+ metadata.gz: 1f4115f58bb2db17cf07a7b9e203ac0fb992acb2db610b32c630ff7628293b24366e9ac18532367556ea3682f8d000aa21e8106aa9105f49a9fbef1dd5f57959
7
+ data.tar.gz: 43e671c27f1e129bed89221f0200106ae584b92292d89c92d82a085123d562c06ddc2ca2368ddf87a0032d1c9c43fe8697ac8902038d04dc52da3582c7fce865
data/.java-version CHANGED
@@ -1 +1 @@
1
- 11
1
+ 11.0
@@ -0,0 +1,4 @@
1
+ ---
2
+ ccrypto-java:
3
+ - :version: 0.1.0
4
+ :timestamp: 1660210263.865093
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 9.4.2.0
data/Gemfile CHANGED
@@ -9,5 +9,5 @@ gem "rake", "~> 13.0"
9
9
 
10
10
  gem "rspec", "~> 3.0"
11
11
 
12
- #gem "ccrypto", git: "ccrypto", branch: 'main'
12
+ gem "ccrypto", git: "ccrypto", branch: 'main'
13
13
 
data/Gemfile.lock CHANGED
@@ -1,70 +1,82 @@
1
- PATH
2
- remote: .
1
+ GIT
2
+ remote: ccrypto
3
+ revision: 4e1c1ce7dea1217b5653558a1473c903e1148e91
4
+ branch: main
3
5
  specs:
4
- ccrypto-java (0.1.0)
5
- ccrypto
6
+ ccrypto (0.2.0)
7
+ activesupport
6
8
  teLogger
7
9
  toolrack
8
10
 
11
+ PATH
12
+ remote: .
13
+ specs:
14
+ ccrypto-java (0.1.8)
15
+ ccrypto (~> 0.2.0)
16
+ teLogger (~> 0.2)
17
+ toolrack (~> 0.23)
18
+
9
19
  GEM
10
20
  remote: https://rubygems.org/
11
21
  specs:
12
- activesupport (6.1.6)
22
+ activesupport (7.1.2)
23
+ base64
24
+ bigdecimal
13
25
  concurrent-ruby (~> 1.0, >= 1.0.2)
26
+ connection_pool (>= 2.2.5)
27
+ drb
14
28
  i18n (>= 1.6, < 2)
15
29
  minitest (>= 5.1)
30
+ mutex_m
16
31
  tzinfo (~> 2.0)
17
- zeitwerk (~> 2.3)
18
- base58 (0.2.3)
19
- ccrypto (0.1.0)
20
- activesupport
21
- teLogger
22
- toolrack
23
- concurrent-ruby (1.1.10)
24
- devops_assist (0.2.0)
25
- git_cli
26
- git_cli_prompt
27
- gvcs
28
- teLogger
29
- toolrack
30
- tty-prompt
32
+ base64 (0.2.0)
33
+ bigdecimal (3.1.5)
34
+ bigdecimal (3.1.5-java)
35
+ colorize (1.1.0)
36
+ concurrent-ruby (1.2.2)
37
+ connection_pool (2.4.1)
31
38
  diff-lcs (1.5.0)
32
- git_cli (0.9.0)
33
- gvcs
39
+ drb (2.2.0)
40
+ ruby2_keywords
41
+ git_cli (0.13.9)
34
42
  ptools (~> 1.4.0)
35
- tlogger
36
- toolrack
37
- git_cli_prompt (0.2.2)
38
- tlogger
39
- toolrack
40
- tty-prompt
41
- gvcs (0.1.0)
42
- i18n (1.10.0)
43
+ teLogger (> 0.2)
44
+ toolrack (> 0.23)
45
+ i18n (1.14.1)
43
46
  concurrent-ruby (~> 1.0)
44
- minitest (5.16.2)
47
+ minitest (5.20.0)
48
+ mutex_m (0.2.0)
45
49
  pastel (0.8.0)
46
50
  tty-color (~> 0.5)
47
- ptools (1.4.2)
48
- rake (13.0.6)
49
- rspec (3.11.0)
50
- rspec-core (~> 3.11.0)
51
- rspec-expectations (~> 3.11.0)
52
- rspec-mocks (~> 3.11.0)
53
- rspec-core (3.11.0)
54
- rspec-support (~> 3.11.0)
55
- rspec-expectations (3.11.0)
51
+ ptools (1.4.3)
52
+ rake (13.1.0)
53
+ release-gem (0.3.3)
54
+ colorize (~> 1.1)
55
+ git_cli (~> 0.13)
56
+ pastel (~> 0.8)
57
+ teLogger (~> 0.2)
58
+ toolrack (~> 0.23)
59
+ tty-command (~> 0.10)
60
+ tty-prompt (~> 0.23)
61
+ rspec (3.12.0)
62
+ rspec-core (~> 3.12.0)
63
+ rspec-expectations (~> 3.12.0)
64
+ rspec-mocks (~> 3.12.0)
65
+ rspec-core (3.12.2)
66
+ rspec-support (~> 3.12.0)
67
+ rspec-expectations (3.12.3)
56
68
  diff-lcs (>= 1.2.0, < 2.0)
57
- rspec-support (~> 3.11.0)
58
- rspec-mocks (3.11.0)
69
+ rspec-support (~> 3.12.0)
70
+ rspec-mocks (3.12.6)
59
71
  diff-lcs (>= 1.2.0, < 2.0)
60
- rspec-support (~> 3.11.0)
61
- rspec-support (3.11.0)
62
- teLogger (0.1.0)
63
- tlogger (0.26.3)
64
- toolrack (0.18.6)
65
- base58
66
- tlogger
72
+ rspec-support (~> 3.12.0)
73
+ rspec-support (3.12.1)
74
+ ruby2_keywords (0.0.5)
75
+ teLogger (0.2.2)
76
+ toolrack (0.24.1)
67
77
  tty-color (0.6.0)
78
+ tty-command (0.10.1)
79
+ pastel (~> 0.8)
68
80
  tty-cursor (0.7.1)
69
81
  tty-prompt (0.23.1)
70
82
  pastel (~> 0.8)
@@ -73,22 +85,25 @@ GEM
73
85
  tty-cursor (~> 0.7)
74
86
  tty-screen (~> 0.8)
75
87
  wisper (~> 2.0)
76
- tty-screen (0.8.1)
77
- tzinfo (2.0.4)
88
+ tty-screen (0.8.2)
89
+ tzinfo (2.0.6)
78
90
  concurrent-ruby (~> 1.0)
79
91
  wisper (2.0.1)
80
- zeitwerk (2.6.0)
81
92
 
82
93
  PLATFORMS
94
+ arm64-darwin-23
83
95
  universal-java-1.8
84
96
  universal-java-11
97
+ universal-java-17
98
+ universal-java-19
85
99
  x86_64-linux
86
100
 
87
101
  DEPENDENCIES
102
+ ccrypto!
88
103
  ccrypto-java!
89
- devops_assist
90
104
  rake (~> 13.0)
105
+ release-gem
91
106
  rspec (~> 3.0)
92
107
 
93
108
  BUNDLED WITH
94
- 2.3.6
109
+ 2.5.1
data/Rakefile CHANGED
@@ -3,8 +3,9 @@
3
3
  require "bundler/gem_tasks"
4
4
  require "rspec/core/rake_task"
5
5
 
6
- require 'devops_assist'
6
+ #require 'devops_assist'
7
7
 
8
8
  RSpec::Core::RakeTask.new(:spec)
9
9
 
10
10
  task default: :spec
11
+ require 'release/gem'
data/bin/console CHANGED
@@ -4,6 +4,20 @@
4
4
  require "bundler/setup"
5
5
  require "ccrypto/java"
6
6
 
7
+ path = File.join(File.dirname(__FILE__),"..","jars","*.jar")
8
+ puts "Loading BC library from #{File.dirname(path)}"
9
+ Dir.glob(path).each do |l|
10
+ require File.expand_path(l)
11
+ end
12
+
13
+ BCPROV = org.bouncycastle.jce.provider.BouncyCastleProvider.new
14
+ if not java.security.Security.get_providers.to_a.include?(BCPROV)
15
+ java.security.Security.add_provider(BCPROV)
16
+ puts "Provider #{BCPROV.name} #{BCPROV.version} loaded and added"
17
+ else
18
+ puts "Provider #{BCPROV.name} #{BCPROV.version} loaded"
19
+ end
20
+
7
21
  # You can add fixtures and/or initialization code here to make experimenting
8
22
  # with your gem easier. You can also use a different console, if you like.
9
23
 
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,42 @@
1
+
2
+
3
+ module Ccrypto
4
+ module Java
5
+
6
+ #
7
+ # Map constants defined in Ccrypto::X509::CertProfile
8
+ module BCConstMapping
9
+
10
+ KeyUsageMapping = {
11
+ digitalSignature: org.bouncycastle.asn1.x509::KeyUsage::digitalSignature,
12
+ nonRepudiation: org.bouncycastle.asn1.x509::KeyUsage::nonRepudiation,
13
+ keyEncipherment: org.bouncycastle.asn1.x509::KeyUsage::keyEncipherment,
14
+ dataEncipherment: org.bouncycastle.asn1.x509::KeyUsage::dataEncipherment,
15
+ keyAgreement: org.bouncycastle.asn1.x509::KeyUsage::keyAgreement,
16
+ keyCertSign: org.bouncycastle.asn1.x509::KeyUsage::keyCertSign,
17
+ crlSign: org.bouncycastle.asn1.x509::KeyUsage::cRLSign,
18
+ encipherOnly: org.bouncycastle.asn1.x509::KeyUsage::encipherOnly,
19
+ decipherOnly: org.bouncycastle.asn1.x509::KeyUsage::decipherOnly
20
+ }
21
+
22
+ ExtKeyUsageMapping = {
23
+ allPurpose: org.bouncycastle.asn1.x509.KeyPurposeId::anyExtendedKeyUsage,
24
+ serverAuth: org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_serverAuth,
25
+ clientAuth: org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_clientAuth,
26
+ codeSigning: org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_codeSigning,
27
+ emailProtection: org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_emailProtection,
28
+ timeStamping: org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_timeStamping,
29
+ OCSPSigning: org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_OCSPSigning,
30
+ #ipSecIKE: "IPSec Initial Key Exchange",
31
+ #msCodeInd: "Microsoft Code Ind",
32
+ #msCodeCom: "Microsoft Code Com",
33
+ #msCtlsign: "Microsoft CTL Sign",
34
+ #msEFS: "Microsoft EFS",
35
+ #dvcs: "DVCS purposes"
36
+ }
37
+
38
+
39
+
40
+ end
41
+ end
42
+ end
@@ -1,4 +1,5 @@
1
1
 
2
+ require 'tempfile'
2
3
 
3
4
  module Ccrypto
4
5
  module Java
@@ -15,13 +16,17 @@ module Ccrypto
15
16
  # end from_hex
16
17
 
17
18
  def to_b64(bin)
18
- String.from_java_bytes(java.util.Base64.encoder.encode(bin))
19
+ String.from_java_bytes(java.util.Base64.encoder.encode(to_java_bytes(bin)))
19
20
  end
20
21
  # end to_b64
21
22
  #
22
23
 
23
24
  def to_b64_mime(bin)
24
- String.from_java_bytes(java.util.Base64.mime_encoder.encode(bin))
25
+ String.from_java_bytes(java.util.Base64.mime_encoder.encode(to_java_bytes(bin)))
26
+ end
27
+
28
+ def from_b64_mime(str)
29
+ java.util.Base64.mime_decoder.decode(str)
25
30
  end
26
31
 
27
32
  def from_b64(str)
@@ -46,9 +51,12 @@ module Ccrypto
46
51
  end
47
52
 
48
53
  def to_java_bytes(val, encoding = nil)
54
+ #logger.debug "Given #{val} to convert to java bytes"
49
55
  case val
50
56
  when String
51
57
  val.to_java_bytes
58
+ when Array
59
+ val.join.to_java_bytes
52
60
  when java.lang.String
53
61
  if not_empty?(encoding)
54
62
  val.getBytes(encoding)
@@ -57,6 +65,15 @@ module Ccrypto
57
65
  end
58
66
  when Ccrypto::Java::ManagedMemoryBuffer
59
67
  val.bytes
68
+ when ::Tempfile
69
+ val.rewind
70
+ baos = java.io.ByteArrayOutputStream.new
71
+ while not val.eof?
72
+ baos.write(val.read(Java::READ_BUF_SIZE).to_java_bytes)
73
+ end
74
+ res = baos.toByteArray
75
+ logger.debug "Tempfile has #{res.length} bytes"
76
+ res
60
77
  else
61
78
  if val.respond_to?(:encoded)
62
79
  val.encoded
@@ -66,6 +83,10 @@ module Ccrypto
66
83
  end
67
84
  end
68
85
 
86
+ def logger
87
+ Ccrypto::Java.logger(:data_conv)
88
+ end
89
+
69
90
  #
70
91
  # Add the methods to class level
71
92
  #
@@ -0,0 +1,95 @@
1
+
2
+ require_relative '../data_conversion'
3
+
4
+ module Ccrypto
5
+ module Java
6
+
7
+ class Argon2Engine
8
+ include DataConversion
9
+ include TR::CondUtils
10
+
11
+ def initialize(conf, &block)
12
+
13
+ raise KDFEngineException, "Argon2 config is expected" if not conf.is_a?(Ccrypto::Argon2Config)
14
+ raise KDFEngineException, "Output bit length (outBitLength) value is not given or not a positive value (Given #{conf.outBitLength})" if is_empty?(conf.outBitLength) or conf.outBitLength <= 0
15
+
16
+ #logger.warn "Memory cost is less then 1GB (recommended value)" if conf.cost < 1024*1024*1024
17
+
18
+ @config = conf
19
+ end
20
+
21
+ def derive(input, outFormat = :binary)
22
+
23
+ gen = org.bouncycastle.crypto.generators.Argon2BytesGenerator.new
24
+ builder = org.bouncycastle.crypto.params.Argon2Parameters::Builder.new
25
+
26
+ logger.debug "outBitLength : #{@config.outBitLength} / #{@config.outBitLength/8} bytes"
27
+ outBuf = ::Java::byte[@config.outBitLength/8].new
28
+
29
+ logger.debug "Iteration : #{@config.iter}"
30
+ builder.withIterations(@config.iter)
31
+
32
+ logger.debug "Cost : #{2**@config.cost}"
33
+ #builder.withMemoryAsKB(@config.cost) # unit here is Kilobyte. Config standardize to byte length
34
+ builder.withMemoryPowOfTwo(@config.cost)
35
+
36
+ logger.debug "Parallel : #{@config.parallel}"
37
+ builder.withParallelism(@config.parallel)
38
+
39
+ logger.debug "Salt : #{to_hex(@config.salt)}"
40
+ builder.withSalt(to_java_bytes(@config.salt))
41
+
42
+ #logger.debug "Secret : #{to_b64(to_java_bytes(@config.secret))}"
43
+ if not (@config.secret.nil? or @config.secret.empty?)
44
+ logger.debug "Secret given #{to_hex(@config.secret)}"
45
+ builder.withSecret(to_java_bytes(@config.secret))
46
+ else
47
+ logger.debug "Empty secret value"
48
+ end
49
+
50
+ case @config.variant
51
+ when :argon2d
52
+ logger.debug "Variant : argon2d"
53
+ builder.withVersion(0)
54
+ when :argon2i
55
+ logger.debug "Variant : argon2i"
56
+ builder.withVersion(1)
57
+ when :argon2id
58
+ logger.debug "Variant : argon2id"
59
+ builder.withVersion(2)
60
+ when :argon2_version_10
61
+ logger.debug "Variant : argon2_version_10"
62
+ # 0x10
63
+ builder.withVersion(16)
64
+ when :argon2_version_13
65
+ logger.debug "Variant : argon2_version_13"
66
+ # 0x13
67
+ builder.withVersion(19)
68
+ else
69
+ raise KDFEngineException, "Unknown variant '#{@config.variant}'"
70
+ end
71
+
72
+ gen.init(builder.build())
73
+
74
+ gen.generateBytes(to_java_bytes(input), outBuf)
75
+
76
+ case outFormat
77
+ when :hex
78
+ to_hex(outBuf)
79
+ when :b64
80
+ to_b64(outBuf)
81
+ else
82
+ outBuf
83
+ end
84
+
85
+ end
86
+
87
+ private
88
+ def logger
89
+ Ccrypto::Java.logger(:argon2_eng)
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+ end
@@ -47,7 +47,8 @@ module Ccrypto
47
47
  ASN1Object.new(type, val)
48
48
 
49
49
  when :int
50
- ASN1Object.new(type,org.bouncycastle.asn1.DERInteger.new(val))
50
+ #ASN1Object.new(type,org.bouncycastle.asn1.DERInteger.new(val))
51
+ ASN1Object.new(type,org.bouncycastle.asn1.ASN1Integer.new(val))
51
52
  #Java::OrgBouncycastleAsn1::DERInteger.new(val)
52
53
 
53
54
  when :bin
@@ -0,0 +1,56 @@
1
+
2
+ require_relative '../data_conversion'
3
+
4
+ module Ccrypto
5
+ module Java
6
+
7
+ class BCryptEngine
8
+ include TR::CondUtils
9
+ include DataConversion
10
+
11
+ def initialize(*args, &block)
12
+ @config = args.first
13
+
14
+ raise KDFEngineException, "Ccrypto::BCryptConfig is expected. Given #{@config}" if not @config.is_a?(Ccrypto::BCryptConfig)
15
+
16
+ @config.salt = SecureRandom.random_bytes(16) if is_empty?(@config.salt)
17
+ end
18
+
19
+ def derive(input, output = :binary)
20
+
21
+ begin
22
+
23
+ binput = to_java_bytes(input)
24
+
25
+ #logger.debug "bcrypt input : #{binput.inspect}"
26
+ logger.debug "bcrypt salt : #{to_hex(@config.salt)}"
27
+ logger.debug "bcrypt cost : #{@config.cost}"
28
+
29
+ res = org.bouncycastle.crypto.generators.BCrypt.generate(binput, to_java_bytes(@config.salt), @config.cost)
30
+
31
+ case output
32
+ when :b64
33
+ to_b64(res)
34
+ when :hex
35
+ to_hex(res)
36
+ else
37
+ res
38
+ end
39
+
40
+ rescue Exception => ex
41
+ raise KDFEngineException, ex
42
+ end
43
+
44
+ end
45
+
46
+
47
+ private
48
+ def logger
49
+ Ccrypto::Java.logger(:bcrypt)
50
+ end
51
+
52
+
53
+ end
54
+
55
+ end
56
+ end