encrypth 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 +7 -0
- data/README.md +70 -0
- data/Rakefile +8 -0
- data/lib/encrypth/archiver.rb +77 -0
- data/lib/encrypth/cipher.rb +75 -0
- data/lib/encrypth/cli.rb +85 -0
- data/lib/encrypth/version.rb +3 -0
- data/lib/encrypth/web_archiver.rb +111 -0
- data/lib/encrypth.rb +8 -0
- metadata +76 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: f9079e1bb667c0dc79fda0fd7e3997ab5529dd33cc62f6725ced36913d236868
|
|
4
|
+
data.tar.gz: 831220a4dbffbb5deac197e876f58ad77b6c4ce80dac9caeb501013b21ff86ff
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 71f8b94819558abbc1fb261a5a77829e50fb4069f2514dd598200db81afd76667be3d11de6110be71c711d35ac15d8ccc29203d7d017824a535f34244313c728
|
|
7
|
+
data.tar.gz: b5bfa2ca6e5d919b52596a2cf4db15a8a9a76bdc1b0e5030dcefc81d6f0857f8de500d92eac701990656df232c1ef17b1aa70bda07800190f36ea629986f2661
|
data/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Encrypth
|
|
2
|
+
|
|
3
|
+
`Encrypth` — это простой Ruby gem для безопасного архивирования и шифрования файлов с помощью AES-256-GCM. Gem был создан в качестве учебного проекта, и в дальнейшем можно ожидать расширение функционала.
|
|
4
|
+
|
|
5
|
+
## Что делает
|
|
6
|
+
|
|
7
|
+
- создает зашифрованный tar-архив из файлов и директорий
|
|
8
|
+
- использует надежный режим шифрования AES-256-GCM
|
|
9
|
+
- генерирует ключ по паролю через PBKDF2-HMAC-SHA256
|
|
10
|
+
- сохраняет соль отдельно в файле `archive.salt`
|
|
11
|
+
- извлекает и расшифровывает содержимое обратно в указанную директорию
|
|
12
|
+
|
|
13
|
+
## Установка
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
bundle install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Использование CLI
|
|
20
|
+
|
|
21
|
+
Синтаксис:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
ruby lib/encrypth.rb <archive> <-e|-d> <...files|destination>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Шифрование
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
ruby lib/encrypth.rb secret.enc -e file1.txt folder2 file3.jpg
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
- `secret.enc` — имя выходного зашифрованного архива
|
|
34
|
+
- `-e` — флаг шифрования
|
|
35
|
+
- перечислите файлы и/или директории для архивации
|
|
36
|
+
- пароль вводится скрыто
|
|
37
|
+
- создается файл соли `secret.enc.salt`
|
|
38
|
+
|
|
39
|
+
### Дешифрование
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
ruby lib/encrypth.rb secret.enc -d output_folder
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- `secret.enc` — существующий зашифрованный архив
|
|
46
|
+
- `-d` — флаг дешифрования
|
|
47
|
+
- `output_folder` — папка для извлечения файлов
|
|
48
|
+
- если папка не указана, используется текущая директория
|
|
49
|
+
|
|
50
|
+
## API
|
|
51
|
+
|
|
52
|
+
`Encrypth` предоставляет базовый API для шифрования и дешифрования данных:
|
|
53
|
+
|
|
54
|
+
- `Encrypth.generate_key` — создает случайный 32-байтовый ключ
|
|
55
|
+
- `Encrypth.from_password(password, salt = nil)` — создает ключ из пароля и соли
|
|
56
|
+
- `Encrypth.new(key).encrypt(data)` — шифрует строку
|
|
57
|
+
- `Encrypth.new(key).decrypt(encrypted_string)` — расшифровывает строку
|
|
58
|
+
|
|
59
|
+
## Структура проекта
|
|
60
|
+
|
|
61
|
+
- `lib/encrypth.rb` — точка входа
|
|
62
|
+
- `lib/encrypth/cli.rb` — CLI-интерфейс
|
|
63
|
+
- `lib/encrypth/cipher.rb` — шифрование AES-256-GCM и PBKDF2
|
|
64
|
+
- `lib/encrypth/archiver.rb` — создание и извлечение tar-архива
|
|
65
|
+
- `demo/encrypthdemo.rb` — демонстрация базового шифрования
|
|
66
|
+
- `test/encrypth_test.rb` — набор тестов на Minitest
|
|
67
|
+
|
|
68
|
+
## Лицензия
|
|
69
|
+
|
|
70
|
+
Проект распространяется под лицензией MIT.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
require "stringio"
|
|
3
|
+
require "find"
|
|
4
|
+
require "rubygems/package"
|
|
5
|
+
|
|
6
|
+
module Encrypth
|
|
7
|
+
class Archiver
|
|
8
|
+
def initialize(cipher)
|
|
9
|
+
@cipher = cipher
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Шифрует содержимое файлов и сохраняет его в виде зашифрованного архива
|
|
13
|
+
def encrypt_files(files, archive_path)
|
|
14
|
+
tar_content = create_tar_archive(files, archive_path)
|
|
15
|
+
encrypted = @cipher.encrypt(tar_content)
|
|
16
|
+
File.binwrite(archive_path, encrypted)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Дешифрует архив и извлекает файлы в указанную директорию
|
|
20
|
+
def decrypt_to_directory(archive_path, destination)
|
|
21
|
+
encrypted = File.binread(archive_path)
|
|
22
|
+
tar_content = @cipher.decrypt(encrypted)
|
|
23
|
+
extract_tar_archive(tar_content, destination)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
# Создает tar-архив из списка файлов и возвращает его содержимое в виде строки
|
|
29
|
+
def create_tar_archive(files, archive_path)
|
|
30
|
+
io = StringIO.new.tap { |s| s.set_encoding("binary") }
|
|
31
|
+
Gem::Package::TarWriter.new(io) do |tar|
|
|
32
|
+
files.each do |file|
|
|
33
|
+
if File.directory?(file)
|
|
34
|
+
add_directory_to_archive(tar, file)
|
|
35
|
+
else
|
|
36
|
+
add_file_to_archive(tar, file)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
io.string
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def add_directory_to_archive(archive, directory)
|
|
44
|
+
Find.find(directory) do |path|
|
|
45
|
+
next if File.directory?(path)
|
|
46
|
+
tar_path = path.sub("#{directory}/", "")
|
|
47
|
+
archive.add_file(tar_path, File.stat(path).mode) do |f|
|
|
48
|
+
f.write(File.binread(path))
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def add_file_to_archive(archive, file)
|
|
54
|
+
tar_path = File.basename(file)
|
|
55
|
+
archive.add_file(tar_path, File.stat(file).mode) do |f|
|
|
56
|
+
f.write(File.binread(file))
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Извлекает файлы из tar-архива, который передается в виде строки
|
|
61
|
+
def extract_tar_archive(archive_content, destination)
|
|
62
|
+
io = StringIO.new(archive_content).tap { |s| s.set_encoding("binary") }
|
|
63
|
+
Gem::Package::TarReader.new(io) do |tar|
|
|
64
|
+
tar.each do |entry|
|
|
65
|
+
path = File.join(destination, entry.full_name)
|
|
66
|
+
if entry.directory?
|
|
67
|
+
FileUtils.mkdir_p(path)
|
|
68
|
+
else
|
|
69
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
70
|
+
File.write(path, entry.read)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require "openssl"
|
|
2
|
+
require "base64"
|
|
3
|
+
require "securerandom"
|
|
4
|
+
|
|
5
|
+
module Encrypth
|
|
6
|
+
class Cipher
|
|
7
|
+
def initialize(key)
|
|
8
|
+
@key = key
|
|
9
|
+
validate_key!
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Шифрует данные и возвращает строку для хранения
|
|
13
|
+
def encrypt(data)
|
|
14
|
+
cipher = OpenSSL::Cipher.new("aes-256-gcm")
|
|
15
|
+
cipher.encrypt
|
|
16
|
+
cipher.key = @key
|
|
17
|
+
|
|
18
|
+
iv = cipher.random_iv
|
|
19
|
+
encrypted = cipher.update(data) + cipher.final
|
|
20
|
+
auth_tag = cipher.auth_tag
|
|
21
|
+
|
|
22
|
+
package(iv, encrypted, auth_tag)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Дешифрует данные из строки, созданной методом encrypt
|
|
26
|
+
def decrypt(string)
|
|
27
|
+
iv, encrypted, auth_tag = unpack(string)
|
|
28
|
+
|
|
29
|
+
cipher = OpenSSL::Cipher.new("aes-256-gcm")
|
|
30
|
+
cipher.decrypt
|
|
31
|
+
cipher.key = @key
|
|
32
|
+
cipher.iv = iv
|
|
33
|
+
cipher.auth_tag = auth_tag
|
|
34
|
+
|
|
35
|
+
cipher.update(encrypted) + cipher.final
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Генерирует случайный ключ (32 байта)
|
|
39
|
+
def self.generate_key
|
|
40
|
+
SecureRandom.random_bytes(32)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Создает ключ из пароля (с солью)
|
|
44
|
+
def self.from_password(password, salt = nil)
|
|
45
|
+
salt ||= SecureRandom.random_bytes(16)
|
|
46
|
+
key = OpenSSL::PKCS5.pbkdf2_hmac(password, salt, 20000, 32, "SHA256")
|
|
47
|
+
{ key: key, salt: salt }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def validate_key!
|
|
53
|
+
if @key.bytesize != 32
|
|
54
|
+
raise Error, "Ключ должен быть 32 байта (получено #{@key.bytesize})"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def package(iv, encrypted, auth_tag)
|
|
59
|
+
[
|
|
60
|
+
Base64.strict_encode64(iv),
|
|
61
|
+
Base64.strict_encode64(encrypted),
|
|
62
|
+
Base64.strict_encode64(auth_tag)
|
|
63
|
+
].join("--")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def unpack(string)
|
|
67
|
+
parts = string.split("--", 3)
|
|
68
|
+
[
|
|
69
|
+
Base64.decode64(parts[0]),
|
|
70
|
+
Base64.decode64(parts[1]),
|
|
71
|
+
Base64.decode64(parts[2])
|
|
72
|
+
]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
data/lib/encrypth/cli.rb
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require "io/console"
|
|
2
|
+
require "base64"
|
|
3
|
+
|
|
4
|
+
module Encrypth
|
|
5
|
+
class CLI
|
|
6
|
+
def self.run(args)
|
|
7
|
+
if args.length < 1
|
|
8
|
+
puts "Использование: encrypth.rb <archive> <flag (-e/-d)> <...files/destination?>"
|
|
9
|
+
exit(1)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
archive = args[0]
|
|
13
|
+
flag = args[1]
|
|
14
|
+
|
|
15
|
+
if flag == "-e"
|
|
16
|
+
if File.exist?(archive)
|
|
17
|
+
puts "Архив #{archive} уже существует. Пожалуйста, выберите другое имя или удалите существующий архив."
|
|
18
|
+
exit(1)
|
|
19
|
+
end
|
|
20
|
+
files = args[2..-1]
|
|
21
|
+
encrypt_files(files, archive)
|
|
22
|
+
elsif flag == "-d"
|
|
23
|
+
if !File.exist?(archive)
|
|
24
|
+
puts "Архив #{archive} не существует."
|
|
25
|
+
exit(1)
|
|
26
|
+
end
|
|
27
|
+
destination = args[2]
|
|
28
|
+
if destination && File.exist?(destination) && !File.directory?(destination)
|
|
29
|
+
puts "Указанный путь #{destination} не является директорией."
|
|
30
|
+
exit(1)
|
|
31
|
+
end
|
|
32
|
+
destination = "." if destination.nil? || destination.empty?
|
|
33
|
+
decrypt_to_directory(archive, destination)
|
|
34
|
+
else
|
|
35
|
+
puts "Неверный флаг. Используйте -e для шифрования или -d для дешифрования."
|
|
36
|
+
exit(1)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.encrypt_files(files, archive)
|
|
41
|
+
password = read_password("Задайте пароль: ")
|
|
42
|
+
cipher_data = Encrypth::Cipher.from_password(password)
|
|
43
|
+
save_salt(archive, cipher_data[:salt])
|
|
44
|
+
cipher = Encrypth::Cipher.new(cipher_data[:key])
|
|
45
|
+
archiver = Encrypth::Archiver.new(cipher)
|
|
46
|
+
archiver.encrypt_files(files, archive)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.decrypt_to_directory(archive, destination)
|
|
50
|
+
password = read_password("Введите пароль: ")
|
|
51
|
+
salt = load_salt(archive)
|
|
52
|
+
cipher_data = Encrypth::Cipher.from_password(password, salt)
|
|
53
|
+
cipher = Encrypth::Cipher.new(cipher_data[:key])
|
|
54
|
+
archiver = Encrypth::Archiver.new(cipher)
|
|
55
|
+
archiver.decrypt_to_directory(archive, destination)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def self.salt_path(archive)
|
|
61
|
+
"#{archive}.salt"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self.save_salt(archive, salt)
|
|
65
|
+
File.binwrite(salt_path(archive), Base64.strict_encode64(salt))
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.load_salt(archive)
|
|
69
|
+
salt_file = salt_path(archive)
|
|
70
|
+
unless File.exist?(salt_file)
|
|
71
|
+
raise "Файл соли не найден. Невозможно восстановить ключ для архива #{archive}."
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
Base64.decode64(File.read(salt_file))
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def self.read_password(prompt)
|
|
78
|
+
print prompt
|
|
79
|
+
$stdout.flush
|
|
80
|
+
password = STDIN.noecho { |io| io.gets }&.chomp || ""
|
|
81
|
+
puts
|
|
82
|
+
password
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
module Encrypth
|
|
2
|
+
class WebArchiver
|
|
3
|
+
SALT_LEN = 32
|
|
4
|
+
IV_LEN = 12
|
|
5
|
+
TAG_LEN = 16
|
|
6
|
+
|
|
7
|
+
def initialize(password)
|
|
8
|
+
@password = password
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def encrypt(files)
|
|
12
|
+
out_path = File.join(Dir.tmpdir, "enc_#{SecureRandom.hex(8)}.tar.enc")
|
|
13
|
+
tar_path = File.join(Dir.tmpdir, "tar_#{SecureRandom.hex(8)}.tar")
|
|
14
|
+
|
|
15
|
+
salt = OpenSSL::Random.random_bytes(SALT_LEN)
|
|
16
|
+
key = derive_key(@password, salt)
|
|
17
|
+
|
|
18
|
+
begin
|
|
19
|
+
create_tar(files, tar_path)
|
|
20
|
+
|
|
21
|
+
cipher = OpenSSL::Cipher.new('aes-256-gcm').encrypt
|
|
22
|
+
cipher.key = key
|
|
23
|
+
iv = cipher.random_iv
|
|
24
|
+
cipher.iv_len = IV_LEN
|
|
25
|
+
cipher.iv = iv
|
|
26
|
+
|
|
27
|
+
File.open(out_path, 'wb') do |out_f|
|
|
28
|
+
out_f.write(salt)
|
|
29
|
+
out_f.write(iv)
|
|
30
|
+
|
|
31
|
+
File.open(tar_path, 'rb') do |tar_f|
|
|
32
|
+
while chunk = tar_f.read(16384)
|
|
33
|
+
out_f.write(cipher.update(chunk))
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
out_f.write(cipher.final)
|
|
37
|
+
out_f.write(cipher.auth_tag)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
{ path: out_path, size: File.size(out_path) }
|
|
41
|
+
ensure
|
|
42
|
+
File.delete(tar_path) if File.exist?(tar_path)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def decrypt(archive_path, destination)
|
|
47
|
+
File.open(archive_path, 'rb') do |file|
|
|
48
|
+
salt = file.read(SALT_LEN)
|
|
49
|
+
iv = file.read(IV_LEN)
|
|
50
|
+
|
|
51
|
+
ciphertext_len = File.size(archive_path) - SALT_LEN - IV_LEN - TAG_LEN
|
|
52
|
+
key = derive_key(@password, salt)
|
|
53
|
+
|
|
54
|
+
cipher = OpenSSL::Cipher.new('aes-256-gcm').decrypt
|
|
55
|
+
cipher.key = key
|
|
56
|
+
cipher.iv = iv
|
|
57
|
+
|
|
58
|
+
ciphertext = file.read(ciphertext_len)
|
|
59
|
+
auth_tag = file.read(TAG_LEN)
|
|
60
|
+
cipher.auth_tag = auth_tag
|
|
61
|
+
|
|
62
|
+
decrypted_data = cipher.update(ciphertext) + cipher.final
|
|
63
|
+
|
|
64
|
+
tar_path = File.join(Dir.tmpdir, "dec_#{SecureRandom.hex(8)}.tar")
|
|
65
|
+
File.binwrite(tar_path, decrypted_data)
|
|
66
|
+
|
|
67
|
+
begin
|
|
68
|
+
extract_tar(tar_path, destination)
|
|
69
|
+
ensure
|
|
70
|
+
File.delete(tar_path) if File.exist?(tar_path)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def derive_key(password, salt)
|
|
78
|
+
OpenSSL::PKCS5.pbkdf2_hmac(password, salt, 100000, 32, 'sha256')
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def create_tar(files, output_path)
|
|
82
|
+
File.open(output_path, 'wb') do |f|
|
|
83
|
+
Gem::Package::TarWriter.new(f) do |tar|
|
|
84
|
+
files.each do |file_path|
|
|
85
|
+
next unless File.exist?(file_path)
|
|
86
|
+
stat = File.stat(file_path)
|
|
87
|
+
tar.add_file_simple(File.basename(file_path), stat.mode, stat.size) do |io|
|
|
88
|
+
File.open(file_path, 'rb') { |src| io.write(src.read) }
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def extract_tar(tar_path, destination)
|
|
96
|
+
File.open(tar_path, 'rb') do |f|
|
|
97
|
+
Gem::Package::TarReader.new(f) do |reader|
|
|
98
|
+
reader.each do |entry|
|
|
99
|
+
target = File.join(destination, entry.full_name)
|
|
100
|
+
if entry.directory?
|
|
101
|
+
FileUtils.mkdir_p(target)
|
|
102
|
+
elsif entry.file?
|
|
103
|
+
FileUtils.mkdir_p(File.dirname(target))
|
|
104
|
+
File.binwrite(target, entry.read)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
data/lib/encrypth.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: encrypth
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Irina Grigorian
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: minitest
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '5.0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '5.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rake
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '13.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '13.0'
|
|
40
|
+
description: a gem with aes-256-gcm standard to make encrypting easy and safe.
|
|
41
|
+
email:
|
|
42
|
+
- irigorian@sfedu.ru
|
|
43
|
+
executables: []
|
|
44
|
+
extensions: []
|
|
45
|
+
extra_rdoc_files: []
|
|
46
|
+
files:
|
|
47
|
+
- README.md
|
|
48
|
+
- Rakefile
|
|
49
|
+
- lib/encrypth.rb
|
|
50
|
+
- lib/encrypth/archiver.rb
|
|
51
|
+
- lib/encrypth/cipher.rb
|
|
52
|
+
- lib/encrypth/cli.rb
|
|
53
|
+
- lib/encrypth/version.rb
|
|
54
|
+
- lib/encrypth/web_archiver.rb
|
|
55
|
+
homepage: https://github.com/smokinblackdog/encrypth.git
|
|
56
|
+
licenses:
|
|
57
|
+
- MIT
|
|
58
|
+
metadata: {}
|
|
59
|
+
rdoc_options: []
|
|
60
|
+
require_paths:
|
|
61
|
+
- lib
|
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
63
|
+
requirements:
|
|
64
|
+
- - ">="
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: 3.0.0
|
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: '0'
|
|
72
|
+
requirements: []
|
|
73
|
+
rubygems_version: 3.6.9
|
|
74
|
+
specification_version: 4
|
|
75
|
+
summary: a simple wrapper for encryption.
|
|
76
|
+
test_files: []
|