obfuskit 0.1.0 → 0.2.0

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: 64dba62899b6d17faac7cb64e3797074bf7d532bda2ed2541b7eaf0a7e831be4
4
- data.tar.gz: eb181aeb2d05fffc68a2c7bc1229ed9524aa5bceebbf648e4ae80d342d8c3e52
3
+ metadata.gz: 95df1da20d19fbbd42f0573e3373d1c08831f65f5a49365418fb98569a3d4c57
4
+ data.tar.gz: 43964e64f7175109de2e033f538a1a42632ff4be5330fa30513fb53651f45a17
5
5
  SHA512:
6
- metadata.gz: 152431909ff9df68577645f73f68cb267662291b3e4ac8e13c95a34dd204718951a238f2d01c5d16d335a69083e79091e420b4103e0f6a35f151e0be8d09890d
7
- data.tar.gz: 3167acf2e668dc3fd4b5eb0a6d1b2d31f6f1d0eeaa98316f8375212baae9b56e0254b22a8a610d77d0b0238d2a832323734381dba8352d9df92e117e063f35ae
6
+ metadata.gz: d2e3716d091ee82c00a397a2d17bd610220bef2678c0402e75582b81c8f5491915b0003196e4e72951aa29a3634eb30223b7c83463a31635f87a3e68c3f47600
7
+ data.tar.gz: 3086262688ba6c838a649a9bcbef677578a6001d5a716748ff0974046f511a58e4e556cd127bc316edfe5bf4e41f4cfde3e5791e9a9b475a2ca5f8fd545c562d
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Martin Gratzer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # ObfusKit
2
+
3
+ ObfusKit is a ruby script to generate obfuscated secrets for `Swift` and `Kotlin`.
4
+
5
+ ## Installation and usage
6
+
7
+ Install the latest version of the gem using:
8
+
9
+ ```
10
+ gem install obfuskit
11
+ ```
12
+
13
+ To generate Swift code run the following command:
14
+
15
+ ```sh
16
+ obfuskit swift SECRET_1 SECRET_2 > generated.swift
17
+ ```
18
+
19
+ It will will create the file `generated.swift` containing an obfuscated version of the environment variables `SECRET_1` and `SECRET_2`.
20
+ This file should be excluded from the git repository and generated at build time.
21
+ The obfuscation salt is regenerated for each run.
22
+
23
+ ```swift
24
+ import Foundation
25
+
26
+ enum ObfusKit {
27
+ static let SECRET_1: String = _o.r([30, 113, 37, 119, 32, 37, 36])
28
+ static let SECRET_2: String = _o.r([24, 117, 35, 119, 38, 33, 34])
29
+
30
+ private class _3f3eccd2e5ea46b39738e5502bda6bef { }
31
+ private static let _o = O(String(describing: _3f3eccd2e5ea46b39738e5502bda6bef.self))
32
+ }
33
+
34
+ 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) ?? "" } }
35
+ ```
36
+
37
+ The same concept applies for the `kotlin` language using:
38
+
39
+ ```sh
40
+ obfuskit kotlin com.myapp.configuration.environment SECRET_1 SECRET_2 > generated.kt
41
+ ```
42
+ It will create the Kotlin version `generated.kt`.
43
+
44
+ ```kotlin
45
+ package com.myapp.configuration.environment
46
+
47
+ object ObfusKit {
48
+ private val _o = O(_6572131328ef462d9d4a05cf4b2a2516::class.java.simpleName)
49
+ private class _6572131328ef462d9d4a05cf4b2a2516
50
+
51
+ val SECRET_1: String = _o.r(byteArrayOf(30, 116, 118, 115, 119, 119, 116))
52
+ val SECRET_2: String = _o.r(byteArrayOf(24, 112, 112, 115, 113, 115, 114))
53
+ }
54
+
55
+ 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)}}
56
+
57
+ ```
58
+
59
+ ## Features
60
+ - [x] Generate Swift
61
+ - [x] Generate Kotlin
62
+ - [x] Read secrets from the Environment
63
+ - [x] Add dynamic salt for obfuscation
64
+ - [x] Support for .env files
65
+ - [x] Use template engine for code generation
66
+ - [ ] Read secrets from 1Password CLI
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/exe/obfuskit ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'obfuskit/generator'
3
+ generator = Obfuskit::Generator.new
4
+ generator.generate()
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'obfuscator'
3
+ require 'securerandom'
4
+ require 'dotenv'
5
+ require 'erb'
6
+
7
+ module Language
8
+ SWIFT = "Swift"
9
+ KOTLIN = "Kotlin"
10
+ end
11
+
12
+ module Obfuskit
13
+
14
+ class Generator
15
+
16
+ def generate()
17
+
18
+ Dotenv.load
19
+ args = ARGV
20
+ language_key = args.shift.downcase
21
+
22
+ language_map = {
23
+ "swift" => Language::SWIFT,
24
+ "kotlin" => Language::KOTLIN,
25
+ "kt" => Language::KOTLIN
26
+ }
27
+
28
+ if language_key != nil && language_map.key?(language_key)
29
+
30
+ salt = SecureRandom.uuid.to_s.gsub("-", "")
31
+ obfuscator = Obfuscator.new("_" + salt)
32
+
33
+ case language_map[language_key]
34
+ when Language::SWIFT
35
+ puts generate_swift(args, obfuscator)
36
+
37
+ when Language::KOTLIN
38
+ puts generate_kotlin(args, obfuscator)
39
+ end
40
+
41
+ else
42
+ STDERR.puts "Please specify a valid language."
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def generate_swift(args, obfuscator)
49
+ values = obfuscated_values_from_env(args, obfuscator)
50
+ generate_with_template("swift", values, nil, obfuscator)
51
+ end
52
+
53
+ def generate_kotlin(args, obfuscator)
54
+ package = args.shift
55
+ if package == nil
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)
60
+ end
61
+ end
62
+
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
67
+ end
68
+
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
+ )
77
+ end
78
+
79
+ end
80
+ end
@@ -1,25 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # A class representing an obfuscator.
2
- class O
4
+
5
+ module Obfuskit
6
+ class Obfuscator
7
+
8
+ attr_reader :salt
9
+
3
10
  # Initializes the obfuscator with a string.
4
11
  # The string is converted to an array of bytes and stored in @c.
5
12
  # The size of the array is stored in @l.
6
- def initialize(s)
7
- s = s.bytes if s.is_a? String
8
- @c = s
9
- @l = @c.size
13
+ def initialize(salt)
14
+ salt = salt.bytes if salt.is_a? String
15
+ @salt = salt
16
+ @length = @salt.size
10
17
  end
11
-
18
+
12
19
  # Obfuscates a string.
13
20
  # The string is converted to an array of bytes and each element is XORed with an element from @c.
14
21
  # The index of the element from @c is the index of the element from the string modulo @l.
15
- def o(v)
16
- v.bytes.map.with_index { |b, i| b ^ @c[i % @l] }
22
+ def obfuscate(value)
23
+ value.bytes.map.with_index { |b, i| b ^ @salt[i % @length] }
17
24
  end
18
-
25
+
19
26
  # Reverses the obfuscation of an array of bytes.
20
27
  # Each element is XORed with an element from @c and the result is converted back to a string.
21
28
  # The index of the element from @c is the index of the element from the array modulo @l.
22
- def r(value)
23
- value.map.with_index { |b, i| b ^ @c[i % @l] }.pack('C*').force_encoding('utf-8')
29
+ def reveal(value)
30
+ value.map.with_index { |b, i| b ^ @salt[i % @length] }.pack('C*').force_encoding('utf-8')
24
31
  end
25
- end
32
+ end
33
+ end
@@ -0,0 +1,12 @@
1
+ package <%= package %>
2
+
3
+ public object ObfusKit {
4
+ private val _o = O(_6572131328ef462d9d4a05cf4b2a2516::class.java.simpleName)
5
+ private class _6572131328ef462d9d4a05cf4b2a2516
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) ?? "" } }
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Obfuskit
4
+ VERSION = "0.2.0"
5
+ end
@@ -0,0 +1,11 @@
1
+ module Obfuskit
2
+ class Generator
3
+ def generate: -> void
4
+
5
+ private
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
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Obfuskit
2
+ class Obfuscator
3
+ @length: Integer
4
+ @salt: String
5
+
6
+ def salt: -> String
7
+ def obfuscate: (String) -> [Integer]
8
+ def reveal: ([Integer]) -> String
9
+ end
10
+ end
data/sig/obfuskit.rbs ADDED
@@ -0,0 +1,3 @@
1
+ module Obfuskit
2
+ VERSION: String
3
+ end
metadata CHANGED
@@ -1,32 +1,40 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: obfuskit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Gratzer
8
- autorequire:
9
- bindir: bin
8
+ autorequire:
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-16 00:00:00.000000000 Z
11
+ date: 2024-01-19 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Environment variable obfuscation for Swift and Kotlin
13
+ description: Generate Swift and Kotlin files with obfuscated environment variables.
14
14
  email: mgratzer@gmail.com
15
15
  executables:
16
16
  - obfuskit
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
- - bin/obfuskit
21
- - lib/O.rb
22
- - lib/Omin.kt
23
- - lib/Omin.swift
24
- - lib/obfuskit.rb
20
+ - LICENSE.txt
21
+ - README.md
22
+ - Rakefile
23
+ - exe/obfuskit
24
+ - lib/obfuskit/generator.rb
25
+ - lib/obfuskit/obfuscator.rb
26
+ - lib/obfuskit/templates/kotlin.erb
27
+ - lib/obfuskit/templates/swift.erb
28
+ - lib/obfuskit/version.rb
29
+ - sig/obfuskit.rbs
30
+ - sig/obfuskit/generator.rbs
31
+ - sig/obfuskit/obfuscator.rbs
25
32
  homepage: https://github.com/mgratzer/obfuskit
26
33
  licenses:
27
34
  - MIT
28
- metadata: {}
29
- post_install_message:
35
+ metadata:
36
+ homepage_uri: https://github.com/mgratzer/obfuskit
37
+ post_install_message:
30
38
  rdoc_options: []
31
39
  require_paths:
32
40
  - lib
@@ -34,15 +42,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
34
42
  requirements:
35
43
  - - ">="
36
44
  - !ruby/object:Gem::Version
37
- version: '0'
45
+ version: 3.0.0
38
46
  required_rubygems_version: !ruby/object:Gem::Requirement
39
47
  requirements:
40
48
  - - ">="
41
49
  - !ruby/object:Gem::Version
42
50
  version: '0'
43
51
  requirements: []
44
- rubygems_version: 3.3.3
45
- signing_key:
52
+ rubygems_version: 3.5.3
53
+ signing_key:
46
54
  specification_version: 4
47
- summary: Environment variable obfuscation for Swift and Kotlin
55
+ summary: Environment variable obfuscation for Swift and Kotlin.
48
56
  test_files: []
data/bin/obfuskit DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'obfuskit'
data/lib/Omin.kt DELETED
@@ -1 +0,0 @@
1
- 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)}}
data/lib/Omin.swift DELETED
@@ -1 +0,0 @@
1
- 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) ?? "" } }
data/lib/obfuskit.rb DELETED
@@ -1,107 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Import the necessary modules and files
4
- require_relative 'O'
5
- require 'securerandom'
6
- require 'dotenv'
7
-
8
- # Define a module for language constants
9
- module Language
10
- SWIFT = "Swift"
11
- KOTLIN = "Kotlin"
12
- end
13
-
14
- # Function to generate Swift code
15
- def generate_swift(args)
16
- # Get the source code for the obfuscator
17
- obfuscator_source = obfuscator_source('Omin.swift')
18
- # Generate a random UUID and remove the hyphens
19
- obfuscation_salt = SecureRandom.uuid.to_s.gsub("-", "")
20
- # Create a new instance of the O class with the obfuscation salt
21
- o = O.new("_" + obfuscation_salt)
22
-
23
- # Start building the Swift code
24
- code = "import Foundation\n\n"
25
- code += "enum ObfusKit {\n"
26
- # For each argument, if it's in the environment variables, add it to the code
27
- args.each_with_index do |arg, index|
28
- if ENV[arg] != nil
29
- code += "\tstatic let #{arg}: String = _o.r(#{o.o(ENV[arg])})\n"
30
- end
31
- end
32
- code += "\n"
33
- # Add the obfuscation salt and the obfuscator to the code
34
- code += <<-STRING
35
- \tprivate class _#{obfuscation_salt} { }
36
- \tprivate static let _o = O(String(describing: _#{obfuscation_salt}.self))
37
- }\n\n
38
- STRING
39
-
40
- # Add the obfuscator source code to the code
41
- code += obfuscator_source
42
- # Return the generated code
43
- return code
44
- end
45
-
46
- # Function to generate Kotlin code
47
- def generate_kotlin(args)
48
- # Get the source code for the obfuscator
49
- obfuscator_source = obfuscator_source('Omin.kt')
50
- # Generate a random UUID and remove the hyphens
51
- obfuscation_salt = SecureRandom.uuid.to_s.gsub("-", "")
52
- # Create a new instance of the O class with the obfuscation salt
53
- o = O.new("_" + obfuscation_salt)
54
-
55
- # Start building the Kotlin code
56
- code = "object ObfusKit {\n"
57
- # Add the obfuscation salt and the obfuscator to the code
58
- code += <<-STRING
59
- \tprivate val _o = O(_#{obfuscation_salt}::class.java.simpleName)
60
- \tprivate class _#{obfuscation_salt}\n
61
- STRING
62
-
63
- # For each argument, if it's in the environment variables, add it to the code
64
- args.each_with_index do |arg, index|
65
- if ENV[arg] != nil
66
- code += "\tval #{arg}: String = _o.r(byteArrayOf(#{o.o(ENV[arg]).map { |i| i.to_s }.join(', ')}))\n"
67
- end
68
- end
69
- code += "}\n\n"
70
-
71
- # Add the obfuscator source code to the code
72
- code += obfuscator_source
73
- # Return the generated code
74
- return code
75
- end
76
-
77
- # Function to get the source code for the obfuscator
78
- def obfuscator_source(file_name)
79
- # Get the full path to the file
80
- source_file_path = File.expand_path(file_name, __dir__)
81
- # If the file exists, read and return its contents
82
- return File.read(source_file_path) if File.exist?(source_file_path)
83
- end
84
-
85
- # MAIN
86
-
87
- language_map = {
88
- "swift" => Language::SWIFT,
89
- "kotlin" => Language::KOTLIN,
90
- "kt" => Language::KOTLIN
91
- }
92
-
93
- Dotenv.load
94
-
95
- args = ARGV
96
- first_arg = args.shift
97
-
98
- if first_arg != nil && language_map.key?(first_arg.downcase)
99
- case language_map[first_arg]
100
- when Language::SWIFT
101
- puts generate_swift(args)
102
- when Language::KOTLIN
103
- puts generate_kotlin(args)
104
- end
105
- else
106
- puts "First argument is not a valid language. Use `swift` or `kotlin`."
107
- end