obfuskit 0.1.2 → 0.2.1

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: 4780130a4c77f313d5ecb10479d96b739fcdc6bcc1f7199bd847b27783b89848
4
- data.tar.gz: f95871c0915fcf8cbacf5c02930bda78ed39cc2dee886450857b1cc72c7324b3
3
+ metadata.gz: f13c1d6e89c565ef55077edab6aeadaf16396a142887df8ccb8fc9e4c1939177
4
+ data.tar.gz: 281bc1d8a5517df52e6f71af31edd5430d52abc5f1a01e953b431c3c5f8f4cee
5
5
  SHA512:
6
- metadata.gz: a14410ebaad463c3672d1d18f447112e5e6180552977525d110b1c19ebd58a68e79685f4560849c9b86dca3573c13bb51ae98e1ea6939840045754037a8dd391
7
- data.tar.gz: 87f6d65646ef72825b6bc3a4f75437ca6b26dd68ead31978ec0663bfac917669946a753ee026cfb053f4385947a1272cf9200b781ac8497461d5ff9d3664c1ea
6
+ metadata.gz: 30d4652e43f1440ffc36b7c90541523719d0f7bb21f8d5d405571b1021f7f763ad6f4963ad2fb8e44532af1e47a9d72da547464b028369351aa512a955982532
7
+ data.tar.gz: 7fe5c1cfe3eaaf5ff2a11d0fd8d40d023bf4ccf6f8a2aefee2d77288437161e8975651697ee60ca1e5bbf2930a98e5328512cf2dafba34e08eb49ed107612561
data/README.md CHANGED
@@ -62,5 +62,5 @@ class O{private val a:ByteArray;private val b:Int;constructor(s:String){a=s.toBy
62
62
  - [x] Read secrets from the Environment
63
63
  - [x] Add dynamic salt for obfuscation
64
64
  - [x] Support for .env files
65
- - [ ] Use template engine for code generation
65
+ - [x] Use template engine for code generation
66
66
  - [ ] Read secrets from 1Password CLI
@@ -2,6 +2,7 @@
2
2
  require_relative 'obfuscator'
3
3
  require 'securerandom'
4
4
  require 'dotenv'
5
+ require 'erb'
5
6
 
6
7
  module Language
7
8
  SWIFT = "Swift"
@@ -16,7 +17,7 @@ module Obfuskit
16
17
 
17
18
  Dotenv.load
18
19
  args = ARGV
19
- first_arg = args.shift
20
+ language_key = args.shift.downcase
20
21
 
21
22
  language_map = {
22
23
  "swift" => Language::SWIFT,
@@ -24,90 +25,56 @@ module Obfuskit
24
25
  "kt" => Language::KOTLIN
25
26
  }
26
27
 
27
- if first_arg != nil && language_map.key?(first_arg.downcase)
28
+ if language_key != nil && language_map.key?(language_key)
28
29
 
29
- # Generate a random UUID and remove the hyphens
30
- obfuscation_salt = SecureRandom.uuid.to_s.gsub("-", "")
31
- # Create a new instance of the O class with the obfuscation salt
32
- obfuscator = Obfuscator.new("_" + obfuscation_salt)
30
+ salt = SecureRandom.uuid.to_s.gsub("-", "")
31
+ obfuscator = Obfuscator.new("_" + salt)
33
32
 
34
- case language_map[first_arg]
33
+ case language_map[language_key]
35
34
  when Language::SWIFT
36
35
  puts generate_swift(args, obfuscator)
36
+
37
37
  when Language::KOTLIN
38
38
  puts generate_kotlin(args, obfuscator)
39
39
  end
40
+
40
41
  else
41
- puts "First argument is not a valid language. Use `swift` or `kotlin`."
42
+ STDERR.puts "Please specify a valid language."
42
43
  end
43
44
  end
44
45
 
45
46
  private
46
- # Function to generate Swift code
47
+
47
48
  def generate_swift(args, obfuscator)
48
- # Start building the Swift code
49
- code = "import Foundation\n\n"
50
- code += "enum ObfusKit {\n"
51
- # For each argument, if it's in the environment variables, add it to the code
52
- args.each_with_index do |arg, index|
53
- if ENV[arg] != nil
54
- code += "\tstatic let #{arg}: String = _o.r(#{obfuscator.obfuscate(ENV[arg])})\n"
55
- end
56
- end
57
- code += "\n"
58
- # Add the obfuscation salt and the obfuscator to the code
59
- code += <<-STRING
60
- \tprivate class _#{obfuscator.salt} { }
61
- \tprivate static let _o = O(String(describing: _#{obfuscator.salt}.self))
62
- }\n\n
63
- STRING
64
-
65
- # Add the obfuscator source code to the code
66
- code += 'struct O { private let c: [UInt8]; private let l: Int; init(_ s: String) { self.init([UInt8](s.utf8)) }; init(_ c: [UInt8]) { self.c = c; l = c.count }; @inline(__always) func o(_ v: String) -> [UInt8] { [UInt8](v.utf8).enumerated().map { $0.element ^ c[$0.offset % l] } }; @inline(__always) func r(_ value: [UInt8]) -> String { String(bytes: value.enumerated().map { $0.element ^ c[$0.offset % l] }, encoding: .utf8) ?? "" } }'
67
- # Return the generated code
68
- return code
49
+ values = obfuscated_values_from_env(args, obfuscator)
50
+ generate_with_template("swift", values, nil, obfuscator)
69
51
  end
70
52
 
71
- # Function to generate Kotlin code
72
53
  def generate_kotlin(args, obfuscator)
73
- # Get the first argument as the package name
74
54
  package = args.shift
75
- # If no package name is provided, return an empty string
76
55
  if package == nil
77
- puts "No package name provided."
78
- return nil
79
- end
80
-
81
- # Start building the Kotlin code
82
- code = "package #{package}\n\n"
83
- code += "object ObfusKit {\n"
84
- # Add the obfuscation salt and the obfuscator to the code
85
- code += <<-STRING
86
- \tprivate val _o = O(_#{obfuscator.salt}::class.java.simpleName)
87
- \tprivate class _#{obfuscator.salt}\n
88
- STRING
89
-
90
- # For each argument, if it's in the environment variables, add it to the code
91
- args.each_with_index do |arg, index|
92
- if ENV[arg] != nil
93
- code += "\tval #{arg}: String = _o.r(byteArrayOf(#{obfuscator.obfuscate(ENV[arg]).map { |i| i.to_s }.join(', ')}))\n"
94
- end
56
+ STDERR.puts "No package name provided."
57
+ else
58
+ values = obfuscated_values_from_env(args, obfuscator)
59
+ generate_with_template("kotlin", values, package, obfuscator)
95
60
  end
96
- code += "}\n\n"
61
+ end
97
62
 
98
- # Add the obfuscator source code to the code
99
- code += 'class O{private val a:ByteArray;private val b:Int;constructor(s:String){a=s.toByteArray(Charsets.UTF_8);b=a.size};fun o(v:String):ByteArray{val d=v.toByteArray(Charsets.UTF_8);return ByteArray(d.size){i->(d[i].toInt() xor a[i%b].toInt()).toByte()}};fun r(value:ByteArray):String{return String(ByteArray(value.size){i->(value[i].toInt() xor a[i%b].toInt()).toByte()},Charsets.UTF_8)}}'
100
- # Return the generated code
101
- return code
63
+ def obfuscated_values_from_env(args, obfuscator)
64
+ args.map { |name|
65
+ ENV[name] != nil ? [name, obfuscator.obfuscate(ENV[name])] : nil
66
+ }.compact.to_h
102
67
  end
103
68
 
104
- # Function to get the source code for the obfuscator
105
- def obfuscator_source(file_name)
106
- # Get the full path to the file
107
- source_file_path = File.expand_path(file_name, __dir__)
108
- # If the file exists, read and return its contents
109
- return File.read(source_file_path) if File.exist?(source_file_path)
69
+ def generate_with_template(template_name, values, package, obfuscator)
70
+ file = File.expand_path("templates/#{template_name}.erb", __dir__)
71
+ template = ERB.new(File.read(file), trim_mode: "-")
72
+ template.result_with_hash(
73
+ values: values,
74
+ package: package,
75
+ salt: obfuscator.salt
76
+ )
110
77
  end
111
- end
112
78
 
79
+ end
113
80
  end
@@ -4,31 +4,30 @@
4
4
 
5
5
  module Obfuskit
6
6
  class Obfuscator
7
- # Initializes the obfuscator with a string.
8
- # The string is converted to an array of bytes and stored in @c.
9
- # The size of the array is stored in @l.
10
- def initialize(salt)
11
- salt = salt.bytes if salt.is_a? String
12
- @salt = salt
13
- @length = @salt.size
14
- end
15
7
 
16
- def salt
17
- @salt
18
- end
8
+ attr_reader :salt
19
9
 
20
- # Obfuscates a string.
21
- # The string is converted to an array of bytes and each element is XORed with an element from @c.
22
- # The index of the element from @c is the index of the element from the string modulo @l.
23
- def obfuscate(value)
24
- value.bytes.map.with_index { |b, i| b ^ @salt[i % @length] }
25
- end
10
+ # Initializes the obfuscator with a string.
11
+ # The string is converted to an array of bytes and stored in @c.
12
+ # The size of the array is stored in @l.
13
+ def initialize(salt)
14
+ @salt = salt || ""
15
+ @salt_bytes = (salt.bytes || []) if salt.is_a? String
16
+ @salt_length = @salt_bytes.size
17
+ end
26
18
 
27
- # Reverses the obfuscation of an array of bytes.
28
- # Each element is XORed with an element from @c and the result is converted back to a string.
29
- # The index of the element from @c is the index of the element from the array modulo @l.
30
- def reveal(value)
31
- value.map.with_index { |b, i| b ^ @salt[i % @length] }.pack('C*').force_encoding('utf-8')
32
- end
19
+ # Obfuscates a string.
20
+ # The string is converted to an array of bytes and each element is XORed with an element from @c.
21
+ # The index of the element from @c is the index of the element from the string modulo @l.
22
+ def obfuscate(value)
23
+ value.bytes.map.with_index { |b, i| b ^ @salt_bytes[i % @salt_length] }
24
+ end
25
+
26
+ # Reverses the obfuscation of an array of bytes.
27
+ # Each element is XORed with an element from @c and the result is converted back to a string.
28
+ # The index of the element from @c is the index of the element from the array modulo @l.
29
+ def reveal(value)
30
+ value.map.with_index { |b, i| b ^ @salt_bytes[i % @salt_length] }.pack('C*').force_encoding('utf-8')
31
+ end
33
32
  end
34
33
  end
@@ -0,0 +1,12 @@
1
+ package <%= package %>
2
+
3
+ public object ObfusKit {
4
+ private val _o = O(<%= salt %>::class.java.simpleName)
5
+ private class <%= salt %>
6
+
7
+ <% values.each do |name, values| -%>
8
+ public val <%= name %>: String = _o.r(byteArrayOf(<%= values.map { |i| i.to_s }.join(', ') %>))
9
+ <% end -%>
10
+ }
11
+
12
+ private class O{private val a:ByteArray;private val b:Int;constructor(s:String){a=s.toByteArray(Charsets.UTF_8);b=a.size};fun o(v:String):ByteArray{val d=v.toByteArray(Charsets.UTF_8);return ByteArray(d.size){i->(d[i].toInt() xor a[i%b].toInt()).toByte()}};fun r(value:ByteArray):String{return String(ByteArray(value.size){i->(value[i].toInt() xor a[i%b].toInt()).toByte()},Charsets.UTF_8)}}
@@ -0,0 +1,12 @@
1
+ import Foundation
2
+
3
+ public enum ObfusKit {
4
+ <% values.each do |name, values| -%>
5
+ public static let <%= name %>: String = _o.r([<%= values.map { |i| i.to_s }.join(', ') %>])
6
+ <% end -%>
7
+
8
+ private final class <%= salt %> { }
9
+ private static let _o = O(String(describing: <%= salt %>.self))
10
+ }
11
+
12
+ private struct O { private let c: [UInt8]; private let l: Int; init(_ s: String) { self.init([UInt8](s.utf8)) }; init(_ c: [UInt8]) { self.c = c; l = c.count }; @inline(__always) func o(_ v: String) -> [UInt8] { [UInt8](v.utf8).enumerated().map { $0.element ^ c[$0.offset % l] } }; @inline(__always) func r(_ value: [UInt8]) -> String { String(bytes: value.enumerated().map { $0.element ^ c[$0.offset % l] }, encoding: .utf8) ?? "" } }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Obfuskit
4
- VERSION = "0.1.2"
4
+ VERSION = "0.2.1"
5
5
  end
data/obfuskit.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/obfuskit/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "obfuskit"
7
+ s.version = Obfuskit::VERSION
8
+ s.summary = "Environment variable obfuscation for Swift and Kotlin."
9
+ s.description = "Generate Swift and Kotlin files with obfuscated environment variables."
10
+ s.authors = ["Martin Gratzer"]
11
+ s.email = "mgratzer@gmail.com"
12
+ s.homepage =
13
+ "https://github.com/mgratzer/obfuskit"
14
+ s.license = "MIT"
15
+ s.executables << "obfuskit"
16
+ s.required_ruby_version = ">= 3.0.0"
17
+ s.metadata["homepage_uri"] = s.homepage
18
+
19
+ # Specify which files should be added to the gem when it is released.
20
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
+ s.files = Dir.chdir(__dir__) do
22
+ `git ls-files -z`.split("\x0").reject do |f|
23
+ (File.expand_path(f) == __FILE__) ||
24
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
25
+ end
26
+ end
27
+ s.bindir = "exe"
28
+ s.executables = s.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29
+ s.require_paths = ["lib"]
30
+ end
@@ -3,8 +3,9 @@ module Obfuskit
3
3
  def generate: -> void
4
4
 
5
5
  private
6
- def generate_kotlin: -> String
7
- def generate_swift: -> String
8
- def obfuscator_source: -> String
6
+ def generate_kotlin: ([String], Obfuscator) -> String
7
+ def generate_swift: ([String], Obfuscator) -> String
8
+ def obfuscated_values_from_env: ([String], Obfuscator) -> Hash[String, [Integer]]
9
+ def generate_with_template: (String, Hash[String, [Integer]], String, Obfuscator) -> String
9
10
  end
10
11
  end
@@ -1,7 +1,13 @@
1
1
  module Obfuskit
2
2
  class Obfuscator
3
- @length: Int
4
- @salt: String
5
- def salt: -> String
3
+ attr_reader salt: String
4
+
5
+ def initialize: (salt: String) -> void
6
+ def obfuscate: (String) -> [Integer]
7
+ def reveal: ([Integer]) -> String
8
+
9
+ private
10
+ attr_reader salt_length: Integer
11
+ attr_reader salt_bytes: [Integer]
6
12
  end
7
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: obfuskit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Gratzer
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-18 00:00:00.000000000 Z
11
+ date: 2024-02-19 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Generate Swift and Kotlin files with obfuscated environment variables.
14
14
  email: mgratzer@gmail.com
@@ -23,7 +23,10 @@ files:
23
23
  - exe/obfuskit
24
24
  - lib/obfuskit/generator.rb
25
25
  - lib/obfuskit/obfuscator.rb
26
+ - lib/obfuskit/templates/kotlin.erb
27
+ - lib/obfuskit/templates/swift.erb
26
28
  - lib/obfuskit/version.rb
29
+ - obfuskit.gemspec
27
30
  - sig/obfuskit.rbs
28
31
  - sig/obfuskit/generator.rbs
29
32
  - sig/obfuskit/obfuscator.rbs
@@ -32,7 +35,7 @@ licenses:
32
35
  - MIT
33
36
  metadata:
34
37
  homepage_uri: https://github.com/mgratzer/obfuskit
35
- post_install_message:
38
+ post_install_message:
36
39
  rdoc_options: []
37
40
  require_paths:
38
41
  - lib
@@ -47,8 +50,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
47
50
  - !ruby/object:Gem::Version
48
51
  version: '0'
49
52
  requirements: []
50
- rubygems_version: 3.5.3
51
- signing_key:
53
+ rubygems_version: 3.5.6
54
+ signing_key:
52
55
  specification_version: 4
53
56
  summary: Environment variable obfuscation for Swift and Kotlin.
54
57
  test_files: []