Base32?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Base32?

Boris Popov, DeepCove Labs (SNN)

Is there a Base32 encoder/decoder readily available somewhere?

 

http://tools.ietf.org/html/rfc3548

 

-Boris

Sr. Software Engineer

DeepCove Labs

4th floor, 595 Howe Street

Vancouver, BC V6C 2T5

Canada

 


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Base32?

mkobetic
"Boris Popov, DeepCove Labs"<[hidden email]> wrote:
> Is there a Base32 encoder/decoder readily available somewhere?

Not sure this will be terribly useful to you, but I got curious how much would the B32 implementation differ from the B64 one in Xtreams. This is a bit more straightforward implementation, possibly not the most efficient, but seems fairly readable to me. I'm having second thoughts on including the #isSeparator filtering directly in the encoding layer, it could be just as easily applied as a separate layer, giving the application more control over it.

ReadStream>>encodingBase32
        "Decodes characters of base-32 encoding into bytes. Ignores any intervening whitespace.
        Automatically ends the stream if it encounters final padding characters $=, or anything else that's not a valid encoding character."
        " ^<TransformReadStream>"
        "
                #('AE======' 'AEBA====' 'AEBAG===' 'AEBAGBA=' 'AEBAGBAFA')
                        collect: [ :each | each reading encodingBase32 rest ]
        "
        | map cache |
        map := [ :char | ('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' indexOf: char) - 1 ].
        cache := ByteString new: 8.
        ^(self transforming: [ :in :out || chars bits bytes i block nibble |
                        chars := [ (in rejecting: #isSeparator) read: 8 into: cache at: 1 ] on: Incomplete do: [ :incomplete | incomplete count ].
                        i := 1. bits := bytes := block := 0.
                        [ i > chars or: [ (nibble := map value: (cache at: i)) negative ]
                        ] whileFalse: [ block :=  (block bitShift: 5) + nibble. bits := bits + 5. i := i + 1 ].
                        [ bits > 7 ] whileTrue: [ bits := bits - 8. out put: ((block bitShift: bits negated) bitAnd: 255). bytes := bytes + 1 ].
                        bytes < 5 ifTrue: [ (Incomplete count: bytes) raise ] ]
        ) buffer: (RingBuffer on: (ByteArray new: 5));
                yourself


WriteStream>>encodingBase32
        "Encodes bytes into characters of base-32 encoding.
        Emits final padding characters ($=) as required, when the stream is closed."
        " ^<TransformWriteStream>"
        "
                (1 to: 5) collect: [ :i | String new writing encodingBase32 write: (ByteArray withAll: (1 to: i)); conclusion ]
        "
        | map cache |
        map := [ :i | 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' at: i + 1 ].
        cache := ByteArray new: 5.
        ^(self transforming: [ :in :out || bytes chars bits block |
                        bytes := [ in read: 5 into: cache at: 1 ] on: Incomplete do: [ :incomplete | incomplete count ].
                        bytes isZero ifTrue: [ Incomplete zero raise ].
                        block := (1 to: bytes) inject: 0 into: [ :total :byte | (total bitShift: 8) + (cache at: byte)].
                        bits := bytes * 8.
                        [ bits > 0 ] whileTrue: [ bits := bits - 5. out put: (map value: ((block bitShift: bits negated) bitAnd: 31)) ].
                        chars := #[ 2 4 5 7 8 ] at: bytes.
                        chars < 8 ifTrue: [
                                8 - chars timesRepeat: [ out put: $= ].
                                (Incomplete count: bytes) raise ] ]
        ) buffer: (RingBuffer on: (ByteArray new: 5));
                yourself

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Base32?

Boris Popov, DeepCove Labs (SNN)
Martin,

Ah, thanks for that. I was hoping there's some package somewhere that I
missed, but this should do as well, I'll give it a whirl. This won't be
for high performance application, so the implementation details are
irrelevant for as long as it produces the correct results.

-Boris

-----Original Message-----
From: [hidden email] [mailto:[hidden email]]
Sent: Monday, November 07, 2011 3:10 PM
To: Boris Popov, DeepCove Labs
Cc: [hidden email]
Subject: Re: [vwnc] Base32?

"Boris Popov, DeepCove Labs"<[hidden email]> wrote:
> Is there a Base32 encoder/decoder readily available somewhere?

Not sure this will be terribly useful to you, but I got curious how much
would the B32 implementation differ from the B64 one in Xtreams. This is
a bit more straightforward implementation, possibly not the most
efficient, but seems fairly readable to me. I'm having second thoughts
on including the #isSeparator filtering directly in the encoding layer,
it could be just as easily applied as a separate layer, giving the
application more control over it.

ReadStream>>encodingBase32
        "Decodes characters of base-32 encoding into bytes. Ignores any
intervening whitespace.
        Automatically ends the stream if it encounters final padding
characters $=, or anything else that's not a valid encoding character."
        " ^<TransformReadStream>"
        "
                #('AE======' 'AEBA====' 'AEBAG===' 'AEBAGBA='
'AEBAGBAFA')
                        collect: [ :each | each reading encodingBase32
rest ]
        "
        | map cache |
        map := [ :char | ('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' indexOf:
char) - 1 ].
        cache := ByteString new: 8.
        ^(self transforming: [ :in :out || chars bits bytes i block
nibble |
                        chars := [ (in rejecting: #isSeparator) read: 8
into: cache at: 1 ] on: Incomplete do: [ :incomplete | incomplete count
].
                        i := 1. bits := bytes := block := 0.
                        [ i > chars or: [ (nibble := map value:
(cache at: i)) negative ]
                        ] whileFalse: [ block :=  (block bitShift: 5) +
nibble. bits := bits + 5. i := i + 1 ].
                        [ bits > 7 ] whileTrue: [ bits := bits - 8. out
put: ((block bitShift: bits negated) bitAnd: 255). bytes := bytes + 1 ].

                        bytes < 5 ifTrue: [ (Incomplete count: bytes)
raise ] ]
        ) buffer: (RingBuffer on: (ByteArray new: 5));
                yourself


WriteStream>>encodingBase32
        "Encodes bytes into characters of base-32 encoding.
        Emits final padding characters ($=) as required, when the stream
is closed."
        " ^<TransformWriteStream>"
        "
                (1 to: 5) collect: [ :i | String new writing
encodingBase32 write: (ByteArray withAll: (1 to: i)); conclusion ]
        "
        | map cache |
        map := [ :i | 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' at: i + 1 ].
        cache := ByteArray new: 5.
        ^(self transforming: [ :in :out || bytes chars bits block |
                        bytes := [ in read: 5 into: cache at: 1 ] on:
Incomplete do: [ :incomplete | incomplete count ].
                        bytes isZero ifTrue: [ Incomplete zero raise ].
                        block := (1 to: bytes) inject: 0 into: [ :total
:byte | (total bitShift: 8) + (cache at: byte)].
                        bits := bytes * 8.
                        [ bits > 0 ] whileTrue: [ bits := bits - 5. out
put: (map value: ((block bitShift: bits negated) bitAnd: 31)) ].
                        chars := #[ 2 4 5 7 8 ] at: bytes.
                        chars < 8 ifTrue: [
                                8 - chars timesRepeat: [ out put: $= ].
                                (Incomplete count: bytes) raise ] ]
        ) buffer: (RingBuffer on: (ByteArray new: 5));
                yourself

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Base32?

Paul Baumann
In reply to this post by Boris Popov, DeepCove Labs (SNN)

Boris,

 

I don't know of any readily available, so here is one...

 

State Replication Protocol (SRP) has a base64 stream encoder, so I added a class named SrpBase32 to do base32. The attached .st file has standard fileout format. The .gs file has the same code as a GS/S upgrade patch. Either would extend SRP 3.1. The code would be compatible with other Smalltalk dialects except for the class declaration syntax.

 

Base64 uses 4 octets (32 bits) to store 3 octets (24 bits) of data using a sequence of 6 bit (64 value) parts. Base64 encoding grows data size by 33%.

 

11111111 22222222 33333333 44444444 : 4 Character series

76543210 76543210 76543210 76543210 : 4 Characters 8-bit group values

##111111 ##222222 ##333333 ##444444 : 4 6-bit Base64 value groups of Base256

##543210 ##543210 ##543210 ##543210 : 4 6-bit Base64 values of Base256

##111111 ##112222 ##222233 ##333333 : 3 8-bit Base256 value groups of Base64

##765432 ##107654 ##321076 ##543210 : 3 8-bit Base256 values of Base64

 

Base32 uses 8 octets (64 bits) to store 5 octets (40 bits) of data using a sequence of 5 bit (32 value) parts. Base32 encoding grows data size by 60%.

 

11111111 22222222 33333333 44444444 55555555 66666666 77777777 88888888 : 8 Character series

76543210 76543210 76543210 76543210 76543210 76543210 76543210 76543210 : 8 Characters 8-bit group values

###11111 ###22222 ###33333 ###44444 ###55555 ###66666 ###77777 ###88888 : 8 5-bit Base32 value groups of Base256

###43210 ###43210 ###43210 ###43210 ###43210 ###43210 ###43210 ###43210 : 8 5-bit Base32 values of Base256

###11111 ###11122 ###22222 ###23333 ###33334 ###44444 ###44555 ###55555 : 5 8-bit Base256 value groups of Base32

###76543 ###21076 ###54321 ###07654 ###32107 ###65432 ###10765 ###43210 : 5 8-bit Base256 values of Base32

 

Here is a simple example of how you might use the encoder alone to write and then read back in base32:

 

| s |

s := SrpBase32 on: (ReadWriteStream on: ByteArray new).

s nextPutAll: (0 to: 255).

^s contents

 

Paul Baumann

 

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of Boris Popov, DeepCove Labs
Sent: Sunday, November 06, 2011 17:39
To: [hidden email]
Subject: [vwnc] Base32?

 

Is there a Base32 encoder/decoder readily available somewhere?

 

http://tools.ietf.org/html/rfc3548

 

-Boris

Sr. Software Engineer

DeepCove Labs

4th floor, 595 Howe Street

Vancouver, BC V6C 2T5

Canada

 



This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired.

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

SrpBase32.st (23K) Download Attachment
SrpBase32.gs (31K) Download Attachment