Skip to content

Commit 3939fb6

Browse files
committed
Commit of qrcode encoder and supporting modules.
Includes demo module with basic png and crypto for a full-cyle demo with a mobile phone.
0 parents  commit 3939fb6

15 files changed

+1612
-0
lines changed

.gitignore

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
*.beam
2+
*.dump
3+
*.lnk
4+
*.log
5+
*.pdf
6+
*.pem
7+
*.png
8+
test/*
9+
work/*

Emakefile

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
% -*- mode:erlang -*-
2+
{"src/*", [{i, "include"}, {outdir, "ebin"}, debug_info, strict_record_tests]}.

LICENSE

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Copyright 2011 Steve Davis <steve@simulacity.com>
2+
Licensed under the Apache License, Version 2.0 (the "License");
3+
you may not use this file except in compliance with the License.
4+
You may obtain a copy of the License at
5+
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.

README.markdown

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
git remote add origin git@github.com:komone/qrcode.git
2+
git push -u origin master
3+
4+
QR Code Encoder
5+
===============
6+
7+
Reference used was ISO/IEC 18004, 1st Edition (2000)
8+
9+
This implementation is informed by my specific needs, i.e. to provide
10+
two-factor authentication for mobile phones running Google Authenticator.
11+
12+
+ "Byte" mode only (don't need e.g. numeric mode or kanji mode).
13+
+ Encode only (no detection/decode).
14+
+ Basic supporting library functions provided (HOTP, PNG image functions) to allow full-cyle demo.
15+
16+
Demo
17+
====
18+
19+
1. Download repo and compile with `erl -make`
20+
2. Install Google Authenticator App on your mobile:
21+
+ iPhone: http://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8
22+
+ Android: https://market.android.com/details?id=com.google.android.apps.authenticator
23+
3. Run demo: `qrcode_demo:run().`
24+
4. Open the generated `qrcode.png` file
25+
5. Scan the qrcode into the phone.
26+
6. Ensure server clock is correct.
27+
7. The value of `qrcode_demo:totp()` should show the same passcode as the phone.
28+
29+
NOTE: This documentation is rather basic as this was open-sourced by specific request!

ebin/qrcode.app

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{application, qrcode,
2+
[{description, "QRCode Encoder"},
3+
{vsn, "1.0.0"},
4+
{modules, [qrcode, qrcode_matrix, qrcode_mask, reedsolomon, gf256, bits, base32]},
5+
{mod, {qrcode, []}},
6+
{registered, []},
7+
{env, []},
8+
{applications, [kernel, stdlib]}
9+
]}.

src/base32.erl

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
%% Copyright 2011 Steve Davis <steve@simulacity.com>
2+
%
3+
% Licensed under the Apache License, Version 2.0 (the "License");
4+
% you may not use this file except in compliance with the License.
5+
% You may obtain a copy of the License at
6+
%
7+
% http://www.apache.org/licenses/LICENSE-2.0
8+
%
9+
% Unless required by applicable law or agreed to in writing, software
10+
% distributed under the License is distributed on an "AS IS" BASIS,
11+
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
% See the License for the specific language governing permissions and
13+
% limitations under the License.
14+
15+
-module(base32).
16+
17+
-export([encode/1, decode/1]).
18+
19+
-define(BASE32_ALPHABET, {
20+
$A, $B, $C, $D, $E, $F, $G, $H,
21+
$I, $J, $K, $L, $M, $N, $O, $P,
22+
$Q, $R, $S, $T, $U, $V, $W, $X,
23+
$Y, $Z, $2, $3, $4, $5, $6, $7
24+
}).
25+
26+
%% RFC 4648
27+
28+
%%
29+
encode(Bin) when is_binary(Bin) ->
30+
Split = 5 * (byte_size(Bin) div 5),
31+
<<Main0:Split/binary, Rest/binary>> = Bin,
32+
Main = << <<(b32e(C))>> || <<C:5>> <= Main0 >>,
33+
encode0(Rest, Main).
34+
35+
encode0(<<>>, Acc) ->
36+
Acc;
37+
encode0(<<A:5, B:3>>, Acc) ->
38+
<<Acc/binary, (b32e(A)), (b32e(B bsl 2)), "======">>;
39+
encode0(<<A:5, B:5, C:5, D:1>>, Acc) ->
40+
<<Acc/binary, (b32e(A)), (b32e(B)), (b32e(C)), (b32e(D bsl 4)), "====">>;
41+
encode0(<<A:5, B:5, C:5, D:5, E:4>>, Acc) ->
42+
<<Acc/binary, (b32e(A)), (b32e(B)), (b32e(C)), (b32e(D)), (b32e(E bsl 1)), "===">>;
43+
encode0(<<A:5, B:5, C:5, D:5, E:5, F:5, G:2>>, Acc) ->
44+
<<Acc/binary, (b32e(A)), (b32e(B)), (b32e(C)), (b32e(D)), (b32e(E)), (b32e(F)), (b32e(G bsl 3)), "=">>.
45+
46+
%%
47+
decode(Bin) when is_binary(Bin) ->
48+
Result = decode(Bin, <<>>),
49+
true = is_binary(Result),
50+
Result.
51+
52+
decode(<<X, "======">>, Acc) ->
53+
Bits = decode0(X) bsr 2,
54+
<<Acc/bits, Bits:3>>;
55+
decode(<<X, "====">>, Acc) ->
56+
Bits = decode0(X) bsr 4,
57+
<<Acc/bits, Bits:1>>;
58+
decode(<<X, "===">>, Acc) ->
59+
Bits = decode0(X) bsr 1,
60+
<<Acc/bits, Bits:4>>;
61+
decode(<<X, "=">>, Acc) ->
62+
Bits = decode0(X) bsr 3,
63+
<<Acc/bits, Bits:2>>;
64+
decode(<<A, Bin/binary>>, Acc) ->
65+
Bits = decode0(A),
66+
decode(Bin, <<Acc/bits, Bits:5>>);
67+
decode(<<>>, Acc) ->
68+
true = is_binary(Acc),
69+
Acc.
70+
71+
decode0(X) when X >= $A, X =< $Z ->
72+
X - $A;
73+
decode0(X) when X >= $2, X =< $7 ->
74+
X - $2 + 26.
75+
76+
b32e(X) ->
77+
element(X + 1, ?BASE32_ALPHABET).
78+
79+

src/bits.erl

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
%% Copyright 2011 Steve Davis <steve@simulacity.com>
2+
%
3+
% Licensed under the Apache License, Version 2.0 (the "License");
4+
% you may not use this file except in compliance with the License.
5+
% You may obtain a copy of the License at
6+
%
7+
% http://www.apache.org/licenses/LICENSE-2.0
8+
%
9+
% Unless required by applicable law or agreed to in writing, software
10+
% distributed under the License is distributed on an "AS IS" BASIS,
11+
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
% See the License for the specific language governing permissions and
13+
% limitations under the License.
14+
15+
-module(bits).
16+
17+
-export([reverse/1, duplicate/2, append/1, bitlist/1, bitstring/1, stringbits/1]).
18+
-compile(export_all).
19+
20+
reverse(Bin) ->
21+
reverse(Bin, <<>>).
22+
reverse(<<X:1, Bin/bits>>, Acc) ->
23+
reverse(Bin, <<X:1, Acc/bits>>);
24+
reverse(<<>>, Acc) ->
25+
Acc.
26+
27+
%%
28+
duplicate(Bin, N) ->
29+
duplicate(Bin, N, <<>>).
30+
duplicate(Bin, N, Acc) when N > 0 ->
31+
duplicate(Bin, N - 1, <<Acc/bits, Bin/bits>>);
32+
duplicate(_, 0, Acc) ->
33+
Acc.
34+
35+
%%
36+
append(List) ->
37+
append(List, <<>>).
38+
append([H|T], Acc) ->
39+
append(T, <<Acc/bits, H/bits>>);
40+
append([], Acc) ->
41+
Acc.
42+
43+
%%
44+
bitlist(Bin) ->
45+
bitlist(Bin, []).
46+
bitlist(<<X:1, Bin/bits>>, Acc) ->
47+
bitlist(Bin, [X|Acc]);
48+
bitlist(<<>>, Acc) ->
49+
lists:reverse(Acc).
50+
51+
%%
52+
bitstring(Bin) ->
53+
bitstring(Bin, <<>>).
54+
bitstring(<<0:1, Bin/bits>>, Acc) ->
55+
bitstring(Bin, <<Acc/binary, $0>>);
56+
bitstring(<<1:1, Bin/bits>>, Acc) ->
57+
bitstring(Bin, <<Acc/binary, $1>>);
58+
bitstring(<<>>, Acc) ->
59+
Acc.
60+
61+
%%
62+
stringbits(Bin) ->
63+
stringbits(Bin, <<>>).
64+
stringbits(<<$0, Bin/binary>>, Acc) ->
65+
stringbits(Bin, <<Acc/bits, 0:1>>);
66+
stringbits(<<$1, Bin/binary>>, Acc) ->
67+
stringbits(Bin, <<Acc/bits, 1:1>>);
68+
stringbits(<<>>, Acc) ->
69+
Acc.

0 commit comments

Comments
 (0)