The meaning of the term "COMP-3 encrypted file" is not clear to me, but I think you are saying that you have a file that was transferred from a zOS (EBCDIC) based system to an ASCII based system and you want to be able to process the values contained in the COMP-3 (packed decimal fields). If that is correct, I have some code and research that is relevant to your need.
I am assuming that the file was converted from EBCDIC to ASCII when it was transferred from zOS.
It is a common misconception that if COMP-3 (packed decimal) data is converted from EBCDIC to ASCII that it gets "corrupted". That is not the case. What you get are values ranging from x'00' - x'0F'. Regardless of whether you are are on an EBCDIC or ASCII based system, the hexadecimal values in that range are the same.
If the data is viewed outside of a hex editor [on either system] it appears to be corrupt. Depending on the code page, the packed decimal number 01234567890 may display as ⌁杅ྉ. However, using a hex editor you can see that the value is actually x'01 23 45 67 89 0F'. Two numbers are stored in a single byte (one digit in each nibble with the last nibble in the last byte being the sign). When each byte is converted from hex the actual numbers are returned. For example, using Lua, if the variable iChar contains x'23', the function oDec = string.format("%X", iChar) returns the text value of "23" which can be converted to a number. By iterating over the entire string of x'01 23 45 67 89 0F' the actual number (01234567890) is returned. The number can be "repacked" by reversing the process.
Sample code to unpack a packed decimal field is shown below:
--[[ Lua 5.2.3 ]]
--[[ Author: David Alley
Written: August 9, 2017 ]]
--[[ Begin Function ]]
function xdec_unpack (iHex, lField, lNumber)
--[[
This function reads packed decimal data (converted from EBCDIC to ASCII) as input
and returns unpacked ASCII decimal numbers.
--]]
if iHex == nil or iHex == ""
then
return iHex
end
local aChar = {}
local aUnpack = {}
local iChar = ''
for i = 1, lField do
aChar[i] = string.byte(iHex, i)
end
for i, iChar in ipairs(aChar) do
local oDec = string.format("%X", iChar)
if string.len(oDec) == 1
then
table.insert(aUnpack, "0" .. oDec) --[[ Handles binary zeros ]]
else
table.insert(aUnpack, oDec)
end
end
if string.len(table.concat(aUnpack)) - 1 ~= lNumber
then
aUnpack[1] = string.sub(aUnpack[1],2,2)
end
return table.concat(aUnpack)
end
--[[ End Function xdec_unpack ]]
--[[ The code below was written for Linux and reads an entire file. It assumes that there is only one field, and that
field is in packed decimal format. Packed decimal format means that the file was transferred from a z/OS (EBCDIC) system
and the data was converted to ASCII.
It is necessary to supply the field length because when Lua encounters binary zeros (common in packed decimal),
they are treated as an "end of record" indicator. The packed length value is supplied by the variable lField and the
unpacked length value is supplied by the variable lNumber.
Since there is only one field, that field by default, is at the end of each record (the field is the record). Therefore,
any "new line" values (0x0a for Linux) must be included when reading records. This is handled by adding 1 to the variable
lField when reading records. Therefore, this code must be modified if there are multiple fields, and/or the packed decimal
field is not the last field in the record.
The sign is dropped from the unpacked value that is returned from the function xdec_unpack by removing the last byte from the
variable Output1 before writing the records. Therefore, this code must be modified if it is necessary to process negative
numbers. ]]
local lField = 7 --[[ This variable is the length of the packed decimal field before unpacking and is required by the
xdec_unpack function. ]]
local lNumber = 12 --[[ This variable is the length of the unpacked decimal field not including the sign. It is required by the
xdec_unpack function. Its purpose is to determine if a high order zero (left zero) is to be removed. This
occurs in situations where the packed decimal field contains an even number of digits. For example,
0123456789. ]]
local sFile = io.open("/home/david/Documents/Lua/Input/Input2.txt", "r")
local oFile = io.open("/home/david/Documents/Lua/Input/Output1.txt", "w")
while true do
sFile:seek("cur")
local sLine = sFile:read(lField + 1)
if sLine == nil then break end
local Output1 = xdec_unpack(sLine, lField, lNumber) --[[ Call function to unpack ]]
Output1 = string.sub(Output1,1, #Output1 - 1) --[[ Remove sign ]]
oFile:write(Output1, "\n")
end
sFile:close()
oFile:close()