Hi there, it seems hex2bytes is really not safe, but depending on the concrete number, it will throw an error. Workaround: using "0" * string(65537, base=16), but this looks really weird.
Can someone explain why such a basic function does not work as described in its own documentation?
julia> hex2bytes(string(65537, base=16))
ERROR: ArgumentError: length of iterable must be even
Stacktrace:
[1] hex2bytes!(dest::Vector{UInt8}, itr::Base.CodeUnits{UInt8, String})
@ Base ./strings/util.jl:847
[2] hex2bytes!
@ ./strings/util.jl:831 [inlined]
[3] hex2bytes(s::String)
@ Base ./strings/util.jl:825
[4] top-level scope
@ REPL[57]:1
I guess at least, the documentation should be updated, it currently reads like above
julia> s = string(12345, base = 16)
"3039"
julia> hex2bytes(s)
2-element Vector{UInt8}:
0x30
0x39
each successive pair of hexadecimal digits in itr gives the value of one byte in the return vector.
(emphasis added). i.e. it is documented on working on pairs of hexadecimal digits, since this is the canonical way to represent bytes as hex.
If you are trying to parse arbitrary hexadecimal numbers that aren’t representations of byte sequences (i.e. which don’t consist of paired hex digits), then you’re doing something different from what hex2bytes was intended for. What is your application?
I agree that the example in the docs with string(n, base=16) is misleading, however.
Do you just want something like digits(UInt8, n, base=256) or perhaps num2bytes(n) = reinterpret(UInt8, [n])? Or if you just want particular bytes you can use shift and mod operations on n.
In general, I would avoid the intermediate step of converting the number to a string and then parsing the string.
thank you both,
everything is indeed clarified already - just the example in the documentation should get an update
my background: I am using JWTs to create authentication pipeline and there the exponent of the private key needs to be given in hex2bytes(int2hexstr(my_exponent)), because JWTs expects this
I am now running with
function int2hexstr(n)
str = string(n, base=16)
iseven(length(str)) ? str : "0" * str
end
Padding unknown (or heck, even known) incoming data in a cryptographic context “to make the algorithm work” is NOT a good idea. Generally, neither is implementing a seemingly simple padding operation - you can introduce subtle bugs that leave your code vulnerable.
If you don’t mind me asking, but how are you generating the input in the first place? Going via regular Int64 or similar things seems much more of a hassle instead of directly generating an array of bytes to pass to e.g. openssl.
for JWTs keys need to be given under yourdomain/jwks in a json format which includes modulus and exponend base64 encoded with some extra url handling.
While there is an easy way to extract the modulus from a private key using openssl, I couldn’t find anything like that for the exponent, hence I am just assuming the default exponent will be used.
So here the answer: I am indeed using plain Int64 value as the source for my exponent because this is the best readable so that I or others can later check that this is really the default exponent.
final comment from my side
(EDIT: for further tips and tricks please ping me per private message or open a new discourse thread, so that this one is not further stacked up)