# Hex2bytes: length of iterable must be even

**URL:** <https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704>\
**Category:** General Usage\
**Tags:** question, base\
**Created:** [April 20, 2023, 1:04pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704 "2023-04-20T13:04:08Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![schlichtanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schlichtanders/32/32145_2.png) [@schlichtanders](https://discourse.julialang.org/u/schlichtanders)\
**Post date:** [April 20, 2023, 1:04pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/1 "2023-04-20T13:04:08Z")

</div>

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
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
julia> s = string(12345, base = 16)
"3039"

julia> hex2bytes(s)
2-element Vector{UInt8}:
 0x30
 0x39

```

what do you think?

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [April 20, 2023, 1:23pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/2 "2023-04-20T13:23:36Z")

</div>

```julia
string(n,base=b, pad=Int(ceil(log(b,n)))+(1-iseven(Int(ceil(log(b,n)))))) # :innocent:

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 20, 2023, 1:29pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/3 "2023-04-20T13:29:53Z")

</div>

> [@schlichtanders](#):
>
> Can someone explain why such a basic function does not work as described in its own documentation?

This behavior corresponds precisely [to its documentation](https://docs.julialang.org/en/v1/base/numbers/#Base.hex2bytes), which states:

> 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.

---

<div class="post-metadata">

**Author:** ![schlichtanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schlichtanders/32/32145_2.png) [@schlichtanders](https://discourse.julialang.org/u/schlichtanders)\
**Post date:** [April 20, 2023, 1:52pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/4 "2023-04-20T13:52:00Z")

</div>

Thank you for the help!

I am trying to get a number to hex bytes and run into this error because I followed the example in the documentation.

---

<div class="post-metadata">

**Author:** ![schlichtanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schlichtanders/32/32145_2.png) [@schlichtanders](https://discourse.julialang.org/u/schlichtanders)\
**Post date:** [April 20, 2023, 1:52pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/5 "2023-04-20T13:52:48Z")

</div>

this is very impressive 🙂 thank you so much

given that cryptic code, I only feel slightly safer, but I feel at least a little safer 🙂

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [April 20, 2023, 2:02pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/6 "2023-04-20T14:02:55Z")

</div>

> [@schlichtanders](#):
>
> I am trying to get a number to hex bytes

Use `digits`:

```julia
julia> digits(65537, base=256)
3-element Vector{Int64}:
 1
 0
 1

julia> digits(12345, base=256)
2-element Vector{Int64}:
 57
 48

```

You’ll have to manually convert to bytes though.

EDIT: 256 instead of 16, of course 🤦

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 20, 2023, 2:04pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/7 "2023-04-20T14:04:17Z")

</div>

> [@schlichtanders](#):
>
> I am trying to get a number to hex bytes

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.

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [April 20, 2023, 2:06pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/8 "2023-04-20T14:06:55Z")

</div>

```julia
julia> hex2bytes(lpad((s=string(65537, base=16);s),(length(s)+1)÷2*2,'0'))
3-element Vector{UInt8}:
 0x01
 0x00
 0x01

```

But it is still awkward.

---

<div class="post-metadata">

**Author:** ![schlichtanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schlichtanders/32/32145_2.png) [@schlichtanders](https://discourse.julialang.org/u/schlichtanders)\
**Post date:** [April 20, 2023, 2:08pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/9 "2023-04-20T14:08:13Z")

</div>

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

```julia
function int2hexstr(n)
    str = string(n, base=16)
    iseven(length(str)) ? str : "0" * str
end

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [April 20, 2023, 2:08pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/10 "2023-04-20T14:08:31Z")

</div>

> [@Dan](#):
>
> But it is still awkward.

Just don’t create unnecessary intermediate strings:

```julia
julia> UInt8.(digits(65537, base=256))
3-element Vector{UInt8}:
 0x01
 0x00
 0x01

```

But in general I agree with @stevengj here - shifting and building it that way is likely better, depending on the ultimate usecase of this.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [April 20, 2023, 2:09pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/11 "2023-04-20T14:09:59Z")

</div>

> [@schlichtanders](#):
>
> 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

Have you considered using [JWT.jl](https://github.com/tanmaykm/JWTs.jl)?

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.

---

<div class="post-metadata">

**Author:** ![schlichtanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schlichtanders/32/32145_2.png) [@schlichtanders](https://discourse.julialang.org/u/schlichtanders)\
**Post date:** [April 20, 2023, 2:12pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/12 "2023-04-20T14:12:18Z")

</div>

> [@stevengj](#):
>
> `digits(UInt8, n, base=256)`

just now I understood that this actually does the same, so yeah, no need to go via a hexstr

---

<div class="post-metadata">

**Author:** ![schlichtanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schlichtanders/32/32145_2.png) [@schlichtanders](https://discourse.julialang.org/u/schlichtanders)\
**Post date:** [April 20, 2023, 2:13pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/13 "2023-04-20T14:13:21Z")

</div>

yes I am using that package.

There is no API for creating the modulus and exponent, so I use openssl and need to do the conversions myself. I guess that is life

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [April 20, 2023, 2:18pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/14 "2023-04-20T14:18:26Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![schlichtanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schlichtanders/32/32145_2.png) [@schlichtanders](https://discourse.julialang.org/u/schlichtanders)\
**Post date:** [April 20, 2023, 2:34pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/15 "2023-04-20T14:34:01Z")

</div>

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)

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [April 20, 2023, 3:14pm UTC](https://discourse.julialang.org/t/hex2bytes-length-of-iterable-must-be-even/97704/16 "2023-04-20T15:14:14Z")

</div>

It’s just for fun. Follow the (serious) adivices of others
