# How to base64encode a BigInt?

**URL:** https://discourse.julialang.org/t/how-to-base64encode-a-bigint/96668
**Category:** General Usage
**Tags:** question
**Created:** [March 27, 2023, 5:14pm UTC](https://discourse.julialang.org/t/how-to-base64encode-a-bigint/96668 "2023-03-27T17:14:35Z")
**Posts on this page:** 5
**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: [March 27, 2023, 5:14pm UTC](https://discourse.julialang.org/t/how-to-base64encode-a-bigint/96668/1 "2023-03-27T17:14:35Z")

</div>

I was surprised finding that base64encode does not work for BigInt. Can someone help?

```julia
julia> using Base64
julia> base64encode(BigInt(1234123))
ERROR: MethodError: no method matching write(::Base64EncodePipe, ::BigInt)
Closest candidates are:
  write(::IO, ::Any) at io.jl:672
  write(::IO, ::Any, ::Any...) at io.jl:673
  write(::IO, ::Union{Float16, Float32, Float64, Int128, Int16, Int32, Int64, UInt128, UInt16, UInt32, UInt64}) at io.jl:686
  ...
Stacktrace:
 [1] write(io::Base64EncodePipe, x::BigInt)
   @ Base ./io.jl:672
 [2] base64encode(f::Function, args::BigInt; context::Nothing)
   @ Base64 /nix/store/0fxg4zpsp5rbjfxn3hic1534rhagymmr-julia-1.8.5/share/julia/stdlib/v1.8/Base64/src/encode.jl:209
 [3] base64encode(args::BigInt; context::Nothing)
   @ Base64 /nix/store/0fxg4zpsp5rbjfxn3hic1534rhagymmr-julia-1.8.5/share/julia/stdlib/v1.8/Base64/src/encode.jl:216
 [4] base64encode(args::BigInt)
   @ Base64 /nix/store/0fxg4zpsp5rbjfxn3hic1534rhagymmr-julia-1.8.5/share/julia/stdlib/v1.8/Base64/src/encode.jl:216
 [5] top-level scope
   @ REPL[9]:1

```

---

<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: [March 27, 2023, 6:56pm UTC](https://discourse.julialang.org/t/how-to-base64encode-a-bigint/96668/3 "2023-03-27T18:56:14Z")

</div>

The basic issue here is that `write` (called [by default from `base64encode`](https://docs.julialang.org/en/v1/stdlib/Base64/#Base64.base64encode)) is not defined for `BigInt` because we don’t have any canonical binary representation for a `BigInt`. But you can still use `BigInt` with base64 I/O if you pick what format you want to write (and read).

For example, you could use the `Serialization` standard library:

```julia
julia> using Serialization, Base64

julia> x = factorial(big(100))
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

julia> str = base64encode(serialize, x)
"N0pMEQQAAAA0EAEGQmlnSW50H06eAQNHTVBEOSFZMWpjeE1aVTJjVjRsSkI4R3NacXloekNRb0ZHOVVFQ0NzR3AwSVJDdjh1SnpLUjdMV0gxY0tMenFaYlRaNml2S0dBQ0txZXdmRVhrbjVmcFM5UHBtajIwMDA="

julia> deserialize(IOBuffer(base64decode(str)))
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

```

which works simply by [reading/writing the `BigInt` from/to the stream as a string in base=62](https://github.com/JuliaLang/julia/blob/6b934f91d1b9c50c5b783b6aa36cf2648999461c/stdlib/Serialization/src/Serialization.jl#L321-L324). (62 is the largest base supported natively by GMP’s string-conversion functions.)

You could also simply call `str = base64encode(println, x)` to use `base=10` (which is less compact), of course, and then call `parse(BigInt, readline(IOBuffer(base64decode(str))))` to read it back. Or use any other base that you want. The point is that you have to pick a format.

---

<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: [March 28, 2023, 6:18am UTC](https://discourse.julialang.org/t/how-to-base64encode-a-bigint/96668/4 "2023-03-28T06:18:27Z")

</div>

Thank you very much. I have one followup question:

Am I right, that I need to use base=10 if I want to base64encode the bigint to be used as modulus in an official json web token?  
The [RFC 7518: JSON Web Algorithms (JWA)](https://www.rfc-editor.org/rfc/rfc7518#section-6.3.1.1) states `It is represented as a Base64urlUInt-encoded value.`

---

<div class="post-metadata">

### Author: ![pfitzseb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pfitzseb/32/45566_2.png) [@pfitzseb](https://discourse.julialang.org/u/pfitzseb)
#### Post date: [March 28, 2023, 8:03am UTC](https://discourse.julialang.org/t/how-to-base64encode-a-bigint/96668/5 "2023-03-28T08:03:16Z")

</div>

I think you probably want something like this (making use of @stevengj’s [`to_bytes`](https://discourse.julialang.org/t/bigint-to-bytes/91107/5)):

```julia
julia> function to_bytes(n::BigInt; bigendian::Bool=true)
           bytes = Vector{UInt8}(undef, (Base.GMP.MPZ.sizeinbase(n, 2) + 7) ÷ 8)
           order = bigendian ? Cint(1) : Cint(-1)
           count = Ref{Csize_t}()
           @ccall "libgmp".__gmpz_export(bytes::Ptr{UInt8}, count::Ref{Csize_t}, order::Cint,
                       1::Csize_t, 1::Cint, 0::Csize_t, n::Ref{BigInt})::Ptr{UInt8}
           @assert count[] ≤ length(bytes)
           return resize!(bytes, count[])
       end
to_bytes (generic function with 1 method)

julia> function base64urlencode(x::BigInt)
           @assert x >= 0
           base64urlencode(x == 0 ? [0x0] : to_bytes(x))
       end
base64urlencode (generic function with 2 methods)

julia> function base64urlencode(bytes::Vector{UInt8})
           str = base64encode(bytes)
           return replace(str, '=' => "", '+' => '-', '/' => '_')
       end
base64urlencode (generic function with 2 methods)

julia> base64urlencode(big"0")
"AA"

julia> base64urlencode(big"1234")
"BNI"

julia> base64urlencode(big"999999999")
"O5rJ_w"

```

Refs:

- [RFC 7515: JSON Web Signature (JWS)](https://www.rfc-editor.org/rfc/rfc7515#appendix-C)
- [RFC 7518: JSON Web Algorithms (JWA)](https://www.rfc-editor.org/rfc/rfc7518#section-2)

---

<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: [March 28, 2023, 2:13pm UTC](https://discourse.julialang.org/t/how-to-base64encode-a-bigint/96668/6 "2023-03-28T14:13:08Z")

</div>

> [@pfitzseb](#):
>
> I think you probably want something like this (making use of @stevengj’s [`to_bytes`](https://discourse.julialang.org/t/bigint-to-bytes/91107/5)):

In Julia 1.9 you can use something like `digits!(Vector{UInt8}(undef, ndigits(n, base=256)), n, base=256)`, which [now uses `gmz_export`](https://github.com/JuliaLang/julia/pull/47774). Note that `UInt8` only works for `n ≥ 0`, however. You can also (in Julia 1.9) call the low-level `Base.GMP.MPZ.export!` directly for more control over byte order etcetera.
