aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/src/ssl_base64.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/src/ssl_base64.erl')
-rw-r--r--lib/ssl/src/ssl_base64.erl129
1 files changed, 129 insertions, 0 deletions
diff --git a/lib/ssl/src/ssl_base64.erl b/lib/ssl/src/ssl_base64.erl
new file mode 100644
index 0000000000..cfc42407e8
--- /dev/null
+++ b/lib/ssl/src/ssl_base64.erl
@@ -0,0 +1,129 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Purpose : Base 64 encoding and decoding.
+
+-module(ssl_base64).
+
+-export([encode/1, encode_split/1, decode/1, join_decode/1]).
+
+-define(st(X,A), ((X-A+256) div 256)).
+-define(CHARS, 64).
+
+%% A PEM encoding consists of characters A-Z, a-z, 0-9, +, / and
+%% =. Each character encodes a 6 bits value from 0 to 63 (A = 0, / =
+%% 63); = is a padding character.
+%%
+
+%%
+%% encode(Bytes|Binary) -> Chars
+%%
+%% Take 3 bytes a time (3 x 8 = 24 bits), and make 4 characters out of
+%% them (4 x 6 = 24 bits).
+%%
+encode(Bs) when is_list(Bs) ->
+ encode(list_to_binary(Bs));
+encode(<<B:3/binary, Bs/binary>>) ->
+ <<C1:6, C2:6, C3:6, C4:6>> = B,
+ [enc(C1), enc(C2), enc(C3), enc(C4)| encode(Bs)];
+encode(<<B:2/binary>>) ->
+ <<C1:6, C2:6, C3:6, _:6>> = <<B/binary, 0>>,
+ [enc(C1), enc(C2), enc(C3), $=];
+encode(<<B:1/binary>>) ->
+ <<C1:6, C2:6, _:12>> = <<B/binary, 0, 0>>,
+ [enc(C1), enc(C2), $=, $=];
+encode(<<>>) ->
+ [].
+
+%%
+%% encode_split(Bytes|Binary) -> Lines
+%%
+%% The encoding is divided into lines separated by <NL>, and each line
+%% is precisely 64 characters long (excluding the <NL> characters,
+%% except the last line which 64 characters long or shorter. <NL> may
+%% follow the last line.
+%%
+encode_split(Bs) ->
+ split(encode(Bs)).
+
+%%
+%% decode(Chars) -> Binary
+%%
+decode(Cs) ->
+ list_to_binary(decode1(Cs)).
+
+decode1([C1, C2, $=, $=]) ->
+ <<B1, _:16>> = <<(dec(C1)):6, (dec(C2)):6, 0:12>>,
+ [B1];
+decode1([C1, C2, C3, $=]) ->
+ <<B1, B2, _:8>> = <<(dec(C1)):6, (dec(C2)):6, (dec(C3)):6, (dec(0)):6>>,
+ [B1, B2];
+decode1([C1, C2, C3, C4| Cs]) ->
+ Bin = <<(dec(C1)):6, (dec(C2)):6, (dec(C3)):6, (dec(C4)):6>>,
+ [Bin| decode1(Cs)];
+decode1([]) ->
+ [].
+
+%%
+%% join_decode(Lines) -> Binary
+%%
+%% Remove <NL> before decoding.
+%%
+join_decode(Cs) ->
+ decode(join(Cs)).
+
+%%
+%% Locals
+%%
+
+%% enc/1 and dec/1
+%%
+%% Mapping: 0-25 -> A-Z, 26-51 -> a-z, 52-61 -> 0-9, 62 -> +, 63 -> /
+%%
+enc(C) ->
+ 65 + C + 6*?st(C,26) - 75*?st(C,52) -15*?st(C,62) + 3*?st(C,63).
+
+dec(C) ->
+ 62*?st(C,43) + ?st(C,47) + (C-59)*?st(C,48) - 69*?st(C,65) - 6*?st(C,97).
+
+%% split encoding into lines
+%%
+split(Cs) ->
+ split(Cs, ?CHARS).
+
+split([], _N) ->
+ [$\n];
+split(Cs, 0) ->
+ [$\n| split(Cs, ?CHARS)];
+split([C| Cs], N) ->
+ [C| split(Cs, N-1)].
+
+%% join lines of encodings
+%%
+join([$\r, $\n| Cs]) ->
+ join(Cs);
+join([$\n| Cs]) ->
+ join(Cs);
+join([C| Cs]) ->
+ [C| join(Cs)];
+join([]) ->
+ [].
+