19

I'm trying to encode an int in to base64, i'm doing that:

foo = 1
base64.b64encode(bytes(foo))

expected output: 'MQ=='

given output: b'AA=='

what i'm doing wrong?

Edit: in Python 2.7.2 works correctly

Asclepius
  • 57,944
  • 17
  • 167
  • 143
fj123x
  • 6,904
  • 12
  • 46
  • 58
  • 1
    Hmm... what version of Python are you using? When I do base64.b64encode(bytes(1)) or foo=1;base64.b64encode(bytes(foo)) I'm getting 'MQ=='. Also, where are you running this on? – Foon Sep 04 '13 at 14:36
  • 1
    When I run your code, I have the expected output. Did you redefine foo somewhere else? try base64.b64encode(b'1') – Samy Arous Sep 04 '13 at 14:38
  • i'm using Python 3.3.2 – fj123x Sep 04 '13 at 14:38
  • in Python 2.7.2 is working :/ – fj123x Sep 04 '13 at 14:39
  • 1
    Confirmed: in Python 3.1.2 it prints `b'AA=='`. The problem is not `b64encode`, it is `bytes()`. In Python3, `bytes(1)` returns `b'00'`. – Robᵩ Sep 04 '13 at 14:40
  • in python3 bytes() works as cast? – fj123x Sep 04 '13 at 14:42
  • @Foon, this uses b'string', how can i do this with a variable? – fj123x Sep 04 '13 at 14:48
  • 2
    NOTE: This is definitely not a duplicate. And none of the answers below are correct. See comments. – Erik Aronesty Aug 01 '18 at 18:54
  • @ErikAronesty Thanks to your comments, I have written a new question and answer: [Python: Efficiently encode large integer as base64](https://stackoverflow.com/questions/54152762/python-efficiently-encode-large-integer-as-base64/). – Asclepius Jan 11 '19 at 19:33

2 Answers2

16

If you initialize bytes(N) with an integer N, it will give you bytes of length N initialized with null bytes:

>>> bytes(10)
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

what you want is the string "1"; so encode it to bytes with:

>>> "1".encode()
b'1'

now, base64 will give you b'MQ==':

>>> import base64
>>> base64.b64encode("1".encode())
b'MQ=='
doep
  • 459
  • 3
  • 4
6

Try this:

foo = 1
base64.b64encode(bytes([foo]))

or

foo = 1
base64.b64encode(bytes(str(foo), 'ascii'))
# Or, roughly equivalently:
base64.b64encode(str(foo).encode('ascii'))

The first example encodes the 1-byte integer 1. The 2nd example encodes the 1-byte character string '1'.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • this is returning `AQ==` instead of `MQ==` – fj123x Sep 04 '13 at 14:46
  • The 2nd example returns `MQ==`. – Robᵩ Sep 04 '13 at 14:49
  • 4
    For others who want to encode integers but don't have expected output: This works, but the encoded string can be much longer than needed. That's because by converting numbers to strings, you're only using a tiny fraction of the input space, but b64encode doesn't know about that (e.g.it doesn't know there'll never be a letter). I think it's better to use the `struct` module to do `b64encode(pack(' – Mark Jan 27 '16 at 15:28
  • 6
    This is the actual answer: `base64.b64encode(i.to_bytes(ceil(i.bit_length()/8),'big'))` Question should NOT be closed. – Erik Aronesty Oct 09 '17 at 22:41
  • @ErikAronesty's answer was the correct one for me. People online don't seem to understand the concept of string -> int (bytes) -> base64 string to produce the shortest string. The answer to the numeric value `29270` should be the base64 string `clY=`. String `"29270"` -> Integer `29270` -> Binary Data `111001001010110` -> Base64 `clY=`. Integer Value `1` -> Binary Data `1` -> Base64 `AQ==`. Really it's `string` -> `base 10` -> `base 64`. – Caesar Kabalan Jan 11 '18 at 02:08
  • @ErikAronesty how would that short approach work if negative numbers are possible? – luckydonald Jul 17 '18 at 17:37
  • @luckydonald use this command for signed, but be aware that converting back needs a similar flag: base64.b64encode(i.to_bytes(ceil(i.bit_length()/8),'big',signed=True)) – Erik Aronesty Aug 01 '18 at 18:45
  • 1
    `base64.b64encode(i.to_bytes((i.bit_length()+8)//8,'big',signed=True))` to get signed converted correctly. and `int.from_bytes(base64.b64decode(z),'big',signed=True)` to decode signed ( i switched to using +8 ... //8 instead of ceil... one less library, and it gives you the extra bit you need for the sign) – Erik Aronesty Aug 01 '18 at 18:52
  • @luckydonald I have written an answer [here](https://stackoverflow.com/a/54152763/832230) formalizing the comments by Erik; it addresses negative numbers too. – Asclepius Jan 11 '19 at 19:59