2021-05-24 01:24:22 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2014-12-31 00:03:17 +08:00
|
|
|
module Zip
|
2022-11-07 01:59:34 +08:00
|
|
|
module TraditionalEncryption # :nodoc:
|
2014-12-31 00:03:17 +08:00
|
|
|
def initialize(password)
|
|
|
|
@password = password
|
|
|
|
reset_keys!
|
|
|
|
end
|
|
|
|
|
|
|
|
def header_bytesize
|
|
|
|
12
|
|
|
|
end
|
|
|
|
|
|
|
|
def gp_flags
|
2015-01-08 17:30:32 +08:00
|
|
|
0x0001 | 0x0008
|
2014-12-31 00:03:17 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
|
|
|
def reset_keys!
|
|
|
|
@key0 = 0x12345678
|
|
|
|
@key1 = 0x23456789
|
|
|
|
@key2 = 0x34567890
|
|
|
|
@password.each_byte do |byte|
|
|
|
|
update_keys(byte.chr)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-02-19 15:28:46 +08:00
|
|
|
def update_keys(num)
|
|
|
|
@key0 = ~Zlib.crc32(num, ~@key0)
|
2024-03-02 06:14:48 +08:00
|
|
|
@key1 = (((@key1 + (@key0 & 0xff)) * 134_775_813) + 1) & 0xffffffff
|
2014-12-31 00:03:17 +08:00
|
|
|
@key2 = ~Zlib.crc32((@key1 >> 24).chr, ~@key2)
|
|
|
|
end
|
|
|
|
|
|
|
|
def decrypt_byte
|
|
|
|
temp = (@key2 & 0xffff) | 2
|
|
|
|
((temp * (temp ^ 1)) >> 8) & 0xff
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-11-07 05:26:37 +08:00
|
|
|
class TraditionalEncrypter < Encrypter # :nodoc:
|
2014-12-31 00:03:17 +08:00
|
|
|
include TraditionalEncryption
|
|
|
|
|
2015-01-08 17:30:32 +08:00
|
|
|
def header(mtime)
|
2014-12-31 00:03:17 +08:00
|
|
|
[].tap do |header|
|
2015-01-08 17:30:32 +08:00
|
|
|
(header_bytesize - 2).times do
|
2015-01-05 22:20:48 +08:00
|
|
|
header << Random.rand(0..255)
|
2014-12-31 00:03:17 +08:00
|
|
|
end
|
2015-01-08 17:30:32 +08:00
|
|
|
header << (mtime.to_binary_dos_time & 0xff)
|
|
|
|
header << (mtime.to_binary_dos_time >> 8)
|
2015-03-23 00:59:33 +08:00
|
|
|
end.map { |x| encode x }.pack('C*')
|
2014-12-31 00:03:17 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def encrypt(data)
|
2015-03-23 00:59:33 +08:00
|
|
|
data.unpack('C*').map { |x| encode x }.pack('C*')
|
2014-12-31 00:03:17 +08:00
|
|
|
end
|
|
|
|
|
2015-01-08 17:30:32 +08:00
|
|
|
def data_descriptor(crc32, compressed_size, uncomprssed_size)
|
2015-03-21 16:27:44 +08:00
|
|
|
[0x08074b50, crc32, compressed_size, uncomprssed_size].pack('VVVV')
|
2015-01-08 17:30:32 +08:00
|
|
|
end
|
|
|
|
|
2014-12-31 00:03:17 +08:00
|
|
|
def reset!
|
|
|
|
reset_keys!
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2020-02-19 15:28:46 +08:00
|
|
|
def encode(num)
|
2014-12-31 00:03:17 +08:00
|
|
|
t = decrypt_byte
|
2020-02-19 15:28:46 +08:00
|
|
|
update_keys(num.chr)
|
|
|
|
t ^ num
|
2014-12-31 00:03:17 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-11-07 05:26:37 +08:00
|
|
|
class TraditionalDecrypter < Decrypter # :nodoc:
|
2014-12-31 00:03:17 +08:00
|
|
|
include TraditionalEncryption
|
|
|
|
|
|
|
|
def decrypt(data)
|
2015-03-23 00:59:33 +08:00
|
|
|
data.unpack('C*').map { |x| decode x }.pack('C*')
|
2014-12-31 00:03:17 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def reset!(header)
|
|
|
|
reset_keys!
|
|
|
|
header.each_byte do |x|
|
|
|
|
decode x
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2020-02-19 15:28:46 +08:00
|
|
|
def decode(num)
|
|
|
|
num ^= decrypt_byte
|
|
|
|
update_keys(num.chr)
|
|
|
|
num
|
2014-12-31 00:03:17 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2015-01-04 02:36:53 +08:00
|
|
|
|
|
|
|
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
|
|
|
# rubyzip is free software; you can redistribute it and/or
|
|
|
|
# modify it under the terms of the ruby license.
|