Download axiomatictokenizer_attach.zip - 1.28 MB
Contents
Screenshots
Source
code license
Introduction
Scope
Features
Context
Service
partners
Sponsored
entities
Payment delay
Inheritors
Arbiters
Subscriptions
Group
authentication
Show
payment history
Recover
compromised service
Administrative
actions
Execution
proof
Signed_documents
Token
submit form
Custom
settings
Known issues
Typical
integration
Adding a
service
Algorithms
Architecture
Reference
code format
Token format
Encrypted
token format
Signed
document format
Weaknesses
Choosing
seeds
Integration
tips
AxiomaticTokenizerKeyGen
Source
code details
Browser
detection
Portability
Color
scheming
Wizard-like
user interface
Translation
Q&A
History
Screenshots
Main screenshot:

"Make payment" / keyboard screenshot:

Source code license
Developed by the AxiomaticId Entity (www.axiomaticid.org).
Released under a "Common Sense License" / "Public
Domain License".
Original author: George Gabriel Hara (www.gardenerofthoughts.org).
Original SHA256 code by Angel Marin, Paul Johnston
(anmar.eu.org/projects/jssha2),
released under a BSD license.
Original BigInteger code by Tom Wu
(www-cs-students.stanford.edu/~tjw/jsbn),
released under a BSD license.
Introduction
This article presents a mechanism to dramatically increase the
security of online financial services, like digital currency services
and banks, by separating the user authentication from the Internet
and by authenticating every action chosen by the user.
The article also presents certain techniques which improve the
quality of JavaScript / HTML applications, like portability, color
scheming, translation and wizard-like user interface.
The implementation, AxiomaticTokenizer, is an open source
application developed in HTML and JavaScript, specifically designed
for mobile devices (like PDAs).
AxiomaticTokenizer works on a
variety of web-browsers: Firefox, InternetExplorer, InternetExplorer
Mobile, Opera, Opera Mobile, Safari.
Scope
Axiomatic tokens separate payments (and
authentication in general) from the medium of communication, mainly
the Internet.
Axiomatic tokens are similar to bank checks, but
they are unforgeable.
It's easy to transfer a token through a service's
web-forms, third party web-proxies, email, mail, phone, pieces of
paper, SMS, and have the payments securely executed.
Features
Multi-service support.
Multi-currency support.
Support for service partners, sponsored entities,
inheritors, group authentication, payment delay, payment arbitration,
subscriptions (/ repeated payments).
The payment history can be hidden from all users.
Account ownership can be reclaimed if the service's
database is compromised.
Actions specific for online payment services.
Service administration actions are included.
Asymmetric encryption (RSA) for sending the shared
secret (derived from the user's passphrase) to the service.
Customizable token integrity code field size. This
is meant to reduce the amount of characters which users need to type.
Optional spy protection for tokens. The disadvantage
of this protection is that it increases significantly the size of the
tokens.
Account name checksums meant to ensure that if the
user types the wrong account name, he is warned about it. Users
should publish their account names together with their checksums,
like this "Alice/65".
Secret account names. By simply adding "#"
at the end of an account name, the account name sent to the service
is actually a mix of the written account name and of the service's
name, in a way which effectively hides the written account name from
the service.
Color themes.
Multi-language support.
Table with mappings
between two dice and characters. This is meant to help users to
generate truly random passphrases.
Multi-platform: Firefox,
InternetExplorer, InternetExplorer Mobile, Opera, Opera Mobile,
Safari.
Easy to check HTML and
JavaScript open source code.
Payment token example
AT1;
MTM; MP; 20081122115157; aliceakula.pub; bobbonkers.pub; NA; AUG; 10;
DET YYM CLR 8G4 SJ5 C9G;
Context
The security of online payments is today under heavy
attack and things are only getting worse as more and more people
start making payments over the Internet. Threats like spyware and
phishing destroy user confidence in online services who are expected
to "do something".
Consider the classical way of making an online
payment: a user creates an account with a service provider, and he
authenticates himself into his account with the account name and a
password. The problem here is that the computer which sends the
password to the service could be infected with spyware, spyware which
could intercept and send the password to a thief who could later log
in the user's account and steal all the digital currency.
This problem could be solved with a dedicated
portable device which can access the Internet, device which would not
allow users to install and run other applications. Such a device
could not, in theory, contain spyware. But software is buggy and it
can never be trusted 100%, particularly not when the amount of code
required to make such a device work is huge.
But there is another way, way which is critical for
the user who means business, the user who manages a lot of digital
currency online. By separating the authentication process from the
communication process, maximum security is reached.
The dedicated device no longer needs to be connected
to the Internet, it simply has to produce the authentication
information which the user can send to the service together with the
request to execute a certain action in his name / account.
Currently, there are such devices, but their problem
is that they generate a token which is not dependent on the payment
information and can therefore be used to authenticate whatever
information leaves a computer infected with spyware and malware,
information which could be different from the one typed by the user
into his web-browser (because it can be modified by malware,
on-the-fly).
For this mechanism to be truly safe, the tokens must
depend on the payment information. The process is straight forward.
The user types into the device all the information which is necessary
to make a payment. Then, the device generates a token, a text which
the user can type into a web-browser on a computer which is connected
to the Internet.
Tokens
Tokens authenticate every action made by the owner
of the account, instead of just the login (as is with passwords).
Every token is unique, and is created in a
deterministic way using cryptographic operations (hashing), so
someone who intercepts it can NOT use it (again) to make a different
payment, like they can in the case of passwords.
A token is generated from the data which has to be
sent to the service (like the account name of the user, the account
name of the recipient of the payment, the amount of currency to be
paid), some dynamic data (like the current time) which makes the
token different every time, and a secret, called shared secret, which
is known to both the user and the service. The shared secret is
generated from the user's passphrase.
A token is like a one-time password. It can be used
to secure data only one time. After it is used, it must be discarded,
else it could be used to perform the same action again. The
difference between a token and a one-time password is that a token
secures the data which has to be sent from the user to the service,
whereas a password is simply used for comparison.
The service verifies that the action requested by
the user was indeed initiated by him, by using the payment
information from the token sent by the user, to generate a token in
the same way. If the two tokens are the same, only the owner of the
account could have sent the user token, so the service can
confidently execute the requested action.
The one thing which makes it impossible for anyone,
other than the user who owns the account and for the service, to
generate the correct token is the shared secret.
The shared secret is sent by the user to the
service, when the user account is created, also using cryptographic
operations (asymmetric encryption), in a way which makes it
impossible for anyone to decipher it. After this, the shared secret
is never sent to the service, like passwords are, but only used to
generate tokens, by both the user and by the service. The way tokens
are generated makes it impossible for anyone to extract the user's
passphrase or the shared secret.
A token contains the plain data which the service
has to know in order to re-create the token on its own, and a hash of
this data. If the user token and the service token are the same, it
means that the shared secret which was used by the user to generate
his token is the same as the shared secret from the user's account.
Thusly, the user and his action are authenticated and the action
requested by the token is executed.
A simple solution
The original intent was to develop a complex
solution, using full asymmetric cryptography (encryption and
signatures), which would cover all technical sides of an online
transaction (not necessarily a payment). The problem of such a
solution is that it's just too complex for generalized use.
From the need to simplify and generalize the use of
secure online payments, AxiomaticTokenizer was born. It is a small
application written in HTML and JavaScript, and is therefore highly
portable, running on all major web-browsers, on various operating
systems, either on desktop computers or on PDAs. AxiomaticTokenizer
is an open source solution which can be peer reviewed easily using a
simple text editor.
A major win for this simplified solution is that
users only need to know their passphrase. A single passphrase is
enough for all services and accounts, because the shared secret is
not the passphrase itself, but a hash of it, and therefore no service
can know the shared secret for any other service or account. Users
don't need to store key pairs, signed documents, encrypted documents,
documents which need to be backed-up, documents which could be lost
(and digital currency along them) or forcefully revealed to thieves.
For users, AxiomaticTokenizer provides a simple,
standardized user interface for making secure payments. For service
providers, integration with the token standard is simple and can be
done with ease. In fact, since AxiomaticTokenizer is released into
the public domain, it can be modify in any way to fit the
requirements of each service.
Simplicity, standardization of user interface and
safety are the key features which make AxiomaticTokenizer the ideal
solution for the generalized use of highly secure payments online.
Who should use it?
Password-based security is extremely simple, so why would a user
trade this simplicity for token-based security which require some
effort to type the tokens?
Users who only have several hundreds dollars worth of digital
currency in their accounts, have no reason to do this. However, the
necessity to protect large amounts of digital currency, starting from
(tens of) thousands of dollars worth of digital currency, motivates
users enough to deal with token-based security.
Service partners
Service partners are entities which bring users to a
service, and they receive a fraction of the payment fee charged by
the service from these users. Service partners help a service grow
faster.
When you create an account with a service, you have
the possibility to specify the account name of the service partner
which recommended the service to you.
If you do specify the account name of a service
partner when you create an account, you will be charged a smaller fee
for every payment you make from that account.
Here is an example of how the payment fee could be
split. The payment fee is 1% from the amount of paid digital
currency. The following percentages are from the fee:
The service gets 40%.
The developer of the application which
generated the token for account creation (or setting change) gets
5%.
If the account has a service partner, the
partner gets 30%, else the service gets it.
If the account has a service partner, the user
gets 20% (as a bonus), else the service gets it.
If the account has a sponsored entity, the
sponsored entity gets 5%, else the service gets it.
Only the entities chosen by the service may be
service partners. This is so that the users, in general, could not be
service partners for their own accounts.
Sponsored entities
When you create an account with a service, you have
the possibility to specify the account name of an entity which you
want to sponsor.
Every time you make a payment, the sponsored entity
(automatically) receives a fraction of the fee which is charged from
you by the service.
If your account has no sponsored entity, the service
gets the entire payment fee.
Only the entities chosen by the service may be
sponsored entities. This is so that the users, in general, could not
be sponsored entities for their own accounts.
Payment delay
If you have an account whose name you make public,
in order to enhance its security, all payments made from the account
can in fact be made some time after you request the service to make
them.
This way, the account acts like a vault with a timed
door, door which, for example, can't physically be opened during the
night.
For security reasons, once the payment delay is set,
it can only be increased (not decreased).
Inheritors
A user account may have inheritors. This is a
feature which lets users specify to the service to automatically move
all the digital currency from their accounts to the inheritor
accounts, in case they become unable to access their own accounts.
Let's consider that Alice, who has an account with
the service, dies or becomes permanently incapacitated to access her
account. Without inheritor accounts, it would be very difficult for
Bob, her husband, and Claudia, her daughter, to receive the inherited
digital currency.
But if Bob and Claudia have an account with the same
service, Alice can add Bob's and Claudia's accounts as inheritor
accounts for her own account. If, during a period of (for example)
one year (the actual value is set when an account is created), Alice
doesn't send any valid token to the service, her account would enter
in inheritance mode, that is, all the digital currency from her
account would be automatically moved to the inheritor accounts, Bob's
and Claudia's account.
The way the digital currency is split depends on how
many inheritance shares Alice allocated for each inheritor.
The number of inheritance shares is specified when
Alice adds an inheritor to her account. The digital currency is
divided for each inheritor as a fraction equal with the number of
inheritance shares allocated for the inheritor divided by the total
number of inheritance shares allocated for all inheritors of that
account.
For example, if Bob has B inheritance shares, and
Claudia has C inheritance shares, Bob receives a fraction equal with
"B / (B + C)" from the digital currency in Alice's account,
and Claudia receives a fraction equal with "C / (B + C)".
Cascading inheritance
The automatic movement of the inherited digital
currency from an account to the inheritor accounts has an interesting
side effect: cascading inheritance.
Let's say that Alice has Bob as inheritor, and Bob
has Claudia as inheritor. If at some point both Alice and Bob become
unable to access their accounts, Claudia will receive the digital
currency from both of them, of course when each account enters into
inheritance mode.
Arbiters
Whenever you want to make a payment in order to buy
something, you can use an arbiter to intermediate the transfer of
digital currency.
To do this, simply type the account name of the
arbiter in the "Arbiter account name" edit-box from the
"Make payment" page, in AxiomaticTokenizer.
When you send the generated token to the service,
the digital currency is taken out of your account and put in a queue
which contains all arbitrated payments, from all users.
At this point the digital currency is still owned by
you, but is under the sole control of the service, and under contract
that it will be sent to the account chosen by the arbiter.
The arbiter can decide to either send the digital
currency back to you or to send it to the recipient of the payment.
The arbiter can not (physically) do anything else with the
digital currency, like disappear with it (unless the arbiter and the
recipient of your payment are the same entity).
Note that if you use an arbiter, you may be charged
an additional payment fee (the maximum fee depends on each service).
Subscriptions
Sometimes you may want to subscribe to a service, or
purchase something in installments, and have the periodic payments
automatically made.
You can use the "Setup subscription"
action to setup a payment which will be made to same account name,
for a specified amount of currency, for a number of times.
The first payment is made when you setup the
subscription, then repeatedly after the timeframe specified there
elapses.
The service may allow the users to change the amount
of currency to pay for the next installment, but only if the amount
is smaller than the initial amount.
Group authentication
Group authentication can be used by organizations to
ensure that access to an account is possible only if a minimum number
of members of the organization agree to execute the same action.
For example, an organization might have an account
with a payment service where it keeps (some of) its money. The
organization would not want any single member to have full access to
this account, but rather ensure that all payment requests are
executed only if at least 3 (out of 5) members of the organization
agree on the payment.
When group authentication is used to execute an
action, all members who generate tokens must type the same
information in AxiomaticTokenizer (except, of course, their own
passphrase). Then, they must send their tokens using a form (provided
by the service) similar to this.
The service checks if all tokens are valid for that
account and ensures that all information from the tokens is the same,
except for the time stamp and for the token integrity code. If all
this is correct, the action is executed.
Two members of a group can't have the same
passphrase or shared secret.
For security reasons, once an account is created,
group authentication can't be changed.
All actions, except "Change passphrase" /
"Claim compromised account" and "Login account",
are affected.
The token submission form of a service (which has
support for group authentication) must provide a way to show enough
edit-boxes where the tokens of the members of the user organization
may be typed.
When an account is created, the number of tokens
typed in the token submission form must be equal with the total
number of members of the group, number specified in the "Create
account" token (of each member). The account can be considered
owned by the group only if all the group members receive back from
the service their "Success" or "LastExecuted"
execution proof, else the account name must be discarded.
In the case of all other actions (affected by group
authentication), the number of tokens must be equal with the required
number of present members; otherwise, the action is not executed.
For all the actions affected by group
authentication, the execution proof is independent for each member of
the group.
Subtlety
It's very important that an action to be executed is
authenticated by the exact required number of present members, not by
more.
Consider that an account has group authentication
set to "3 / 9" (3 out of 9).
If a payment is being made and all 9 members
generate tokens for the payment request, an attacker who could
intercept the token submit form could split the 9 tokens in 3 sets,
and then send them to the service as separate payment requests.
Since the tokens don't have a way to identify that
they refer to the same unique action, the service can't tell that all
3 sets do in fact refer to the same unique payment and it would
execute execute all 3 payments.
The token time stamp could be used as a way to
identify the same unique action for any number of tokens, however
that would require that all group members synchronize it so that the
service could mandate that it too be the same for all the tokens of
the group sent in the same token submit form.
Show payment history
People will always need a public account where to
receive digital currency, but they also need an account which can be
hidden from anyone else; "hidden" doesn't mean hidden from
the service, but from other people.
The problem is how to transfer currency from the
public account to the hidden account, without other people ever
knowing of the transfer. This is solved, by the service, by not
keeping the history for all the payments into and out of the public
account.
In order allow this, AxiomaticTokenizer lets users
specify whether to keep or not the history of all the payments for an
account. For security reasons, this can be only specified when an
account is created, or changed later from "Yes" to "No"
(never from "No" to "Yes").
Even if the user chooses to not keep the history of
the payments, the service may still keep it internally, but it's
guaranteed that no other user will see it.
This feature isn't useful for organizations who need
to keep track of the payments they receive and make, but they can use
delayed payments and group authentication anyway.
Individuals may find this feature to be the only one
to protect them from criminals who would want to see what currency
they have in their accounts, how much currency has entered into the
accounts and to what accounts was the currency moved.
Recover a compromised
service
What happens if a service
experiences a security breach and all the shared secrets of its users
become accessible to thieves?
AxiomaticTokenizer
includes a mechanism for recovering from such events.
Here are the step which
must be taken by the service:
Restart the service
with all accounts locked. Since the current shared secrets are
compromised, they can no longer be used to authenticate actions, so
the users must change the passphrases of their accounts using the
"Claim compromised account" action.
Users can now reclaim the
ownership of their accounts by using the "Claim compromised
account" action.
In order for the service
to be sure that the passphrase of an account is indeed changed by its
actual owner, and not by a thief who has access to the shared
secrets, the token which is used to claim a compromised account
contains the pre-hash of the current shared secret. The service must
check that the hash of the received pre-hash is the same as the
current shared secret.
Administrative actions
Administrative actions may be executed only by
certain users and deeply affect the functioning of the service. See
this for the available
administrative actions.
Any user can generate tokens for administrative
actions (using AxiomaticTokenizer), but in order for such a token to
be executed by the service, the account in whose name the token is
being executed must be allowed to perform the requested action.
Administrative actions may be associated to any
existing account, for instance by using the service's management
software or by using "Change admin actions" tokens.
DO NOT associate administrative actions to an
account before it's created, because someone else might create
the account before the intended entity, and thus gain administrative
privileges.
Encrypted tokens
Tokens may be asymmetrically encrypted with the
public RSA key, included in AxiomaticTokenizer, of the service where
the token is to be sent.
Encrypted tokens may be sent through unencrypted
communication channels, without revealing their content.
The tokens for creating an account, for changing the
account's passphrase and for claiming a compromised account are (and
must) always be encrypted.
All other tokens may be unencrypted (although they
can also be encrypted), and this is preferred for the following
reasons:
Are shorter, so the user can type them.
The user can be sure that the application which
generates such tokens hasn't changed the typed data and hid it
inside the encrypted envelope.
Execution proof
AxiomaticTokenizer automatically computes, and
displays to the user, a number of texts called "execution
proof", for all tokens.
An execution proof is computed in a unique way, from
all the token fields (which are used to compute the token integrity
code).
The service must always compute and include an
execution proof in the response sent to the user, so long as the
token's integrity could be verified. If the token's integrity can't
be verified, like when it is malformed, no execution proof must be
sent to the user.
For all the actions affected by group
authentication, the execution proof is independent for each member of
the group.
An execution proof may not be sent if the token is
queued for later execution.
The user can then compare the execution proof sent
by the service with one displayed by AxiomaticTokenizer. If there is
a match, it means that the service guarantees to the user the what
the execution proof means has indeed happened.
Types of execution proof
Conditions must be evaluated in the order
presented here.
"Success": This must be sent only
if the requested action was successfully executed.
"LastExecuted": This must be sent only
if the token is identical with the last successfully executed token.
"Expired": This must be sent only
if time stamp of the token is smaller than the time stamp of the last
successfully executed token, or if it's bigger than the current time
with 5 minutes (this margin of error is for cases when clocks are
desynchronized). This must not be sent if the "LastExecuted"
execution proof should be sent.
"Error": This must be sent in any other
case. If a "Create account" token can't create the
requested account, the service has to send this execution error
proof.
Reason
Without execution proofs, the account creation phase
would be exposed to potential MITM (= Man-In-The-Middle) attacks, if
the attacker could intercept all the Internet traffic of the user who
wants to create an account.
To do this, the attacker would have to intercept the
original "Create account" token and not forward it to the
service. As such, the service would not have an account with the name
specified in the token, and so nobody could make payments to it.
Later, when the user would try to access his
account, he would likely do it with an unencrypted token, token which
would expose the account's name. At this point the attacker would
intercept the user's token and send to the service a (shadow) token
in order to create the account with the name specified by the user,
but with a shared secret known by the attacker.
From this moment on, the attacker would in fact own
the account with that name, without anyone's knowledge. At least
until he could no longer replace the user's tokens with his own
(shadow) tokens, like when the user would use another computer to
connect to the Internet.
To prevent this, the user must compare the execution
proof sent by the service with the ones displayed by
AxiomaticTokenizer.
Since the "Create account" token is
encrypted and only the service can decrypt it, nobody else can
compute the execution proofs. So, if the service sends back to the
user the "Success" execution proof , the user can be sure
that his token was indeed processed by the service, and that the
account with the name chosen by him is accessible only with his
shared secret.
All the other types of tokens are intrinsically
secure against MITM attacks, so for them the execution proofs
provides only assurance that the token was processed by the service
and it wasn't stopped on its way by an attacker (who then sent back
to the user a response as if it's coming from the service).
Signed documents
AxiomaticTokenizer can process signed documents.
Besides verifying signatures, it may also perform further processing,
like importing service information (this feature is not implemented
yet).
See this for
technical details.
Example
********** Begin
AxiomaticTokenizer Document **********
AEB 00F 2B4 25A
DD2 F15 A77 83B 060 553 D23 25C 623 7A7 AA8 5A6 ED9 BA3 FFD E60 ABF B
-------------------
Begin signature -------------------
Version=1;
Type=Authenticate
AxiomaticTokenizer;
FFA=BckSha256;
ServiceName=AxiomaticTokenizer;
ServiceSeed=CO6OS5PKPS57N948OV5J;
KeyId=S1;
Time=20081226-132653;
Salt=C8F 5CF E3F
62C 0D2 CA0 B6;
TextSize=85;
Value=01B A5E
3F3 E76 8D2 BCE C92 E0F BA9 CAF 59C 7A9 80D 91F 9B7 0AF 35F 045 5A8
C51 85A 64D D9D 30C 748 25E 63D 425 9E8 377 ACA E2A 6CE FFA 269 69C
09C 1FD E47 B24 8B2 C97 1A9 CB3 67A FCD C82 2FF B68 23E A17 144 AF2
366 0DA DF2 706 480 A92 498 D44 06B F63 67E 9CC 3E9 8CB 804 652 00B
073 030 40F 6C1 8E7 6CE 79A 717 D6B EBC 15A 918 845 425 5E8 20E 352
835 897 FB7 F1A 646 FC1 603 82B 856 BEB E6A E90 A45 94F E64 8C1 83A
A72 E9F 5EA C7B 098 A40 1B4 CDF 41C 381 995 BBE E5E A7D 874 5DF 0B4
6BC 80D 00E E23 14E EC9 01E 74A 1F9 47B F62 BEF 957 868 028 0A6 F18
B2F 78E 5FA 431 CB8 1D8 851 D32 CEB 755 CA6 FAA 20C BAD 71D 2BC 721
C84 CEA EE7 F71 6B3 7B8 0E7 ADC A7D 5A1 531 149 54C DDC 0BA 0D;
*********** End
AxiomaticTokenizer Document ***********
Token submit form
Services can use the token submit form included in
the attached archive, where users can type their generated tokens.
You need to customize it to fit your specific
requirements.
Although this form can be made to work offline so
that the users could simply type tokens in it, this would mean lost
flexibility for service providers.
Custom
settings
A service may want to
give to its users the possibility to download and use the original
AxiomaticTokenizer, but with some customized internal values, like
the default language and color scheme.
Since AxiomaticTokenizer
can't be changed, it means that only its file name may be changed.
The file name may contain custom settings in the form "name=value",
all separated by "_" (including the first one). Some custom
settings may be lists, in which case the items of the list are
separated by ",".
AxiomaticTokenizer parses
the name of the file form where it is started and changes some
internal values to match those specified.
Here is the list of
possible custom settings:
"clr" =
the name of the initial color scheme.
"kb" =
show the screen keyboard. If the value of this settings is "true",
the keyboard is displayed, else it is hidden.
"lng" =
the ID of the initial language.
"spart" =
the default service partner account name.
"vsid" = a
list of the IDs of the services which will be visible to the user in
the "Service name" combo-box. If this is missing, all
service names are visible.
If a custom setting is
not specified, the internal default value is used.
Here is an example of a
file name which contains custom settings: "axiomatictokenizer _
clr=paleblue _ lng=ro _ vsid=MTM, FTM.htm" (ignore the blank
spaces). When AxiomaticTokenizer is started from a file with this
name, the initial color scheme is pale-blue, the initial language is
Romanian, and the visible service names are only "Metal Money"
and "Fiat Money".
Known issues
From Opera 9.5, this
isn't an issue anymore. Opera 9.24 and Opera Mobile 8.65 don't
visually update the combo-box items which are automatically selected.
From Firefox 3, this
isn't an issue anymore. Firefox sometimes doesn't activate the
function to copy text (from outside a text-box) to clipboard. If this
happens, first select some text from a text-box, then select and copy
the text of a token.
InternetExplorer 8 beta 2
doesn't properly handle UNIX style line breaks, so AxiomaticTokenizer
may fail to load (depending on what text editor was used).
In order to properly see
the integrated keyboard and the "Dice – character mappings"
table on InternetExplorer Mobile, the "Menu \ View \ One column"
setting must not be set.
Typical integration
AxiomaticTokenizer is only the client side, the user
interface. An online payment service has to implement the server
side, that is, code which parses the incoming tokens and executes the
requested actions in the database.
Once your service accepts
tokens compatible with this standard, you can to integrate your
information in AxiomaticTokenzier.
You have to include the
following information:
Does the service
information have to be visible to the user?
Service name, like
"Metal Money". This must have at least 3 characters and
must be unique.
Service seed. This
must have at least 20 random characters, must be unique, and may
never be changed.
Service ID, like
"MTM" (for "Metal Money"). The service ID should
be short because all tokens include it, and the user has to type it.
This must have at least 3 characters and must be unique.
The date from which
the information is valid. This has the same format as a time stamp,
but must contain only the date (not the clock).
The weblinks where
the user can find the forms where tokens may be typed and submitted
to the service for processing. There is more than one weblink in
order to mitigate DDOS attacks.
The newest version
for processable tokens.
Accepted service
actions. See the available actions below.
Does the
service have support for service partners? See Service
partners for details.
Does the
service have support for sponsored entities? See Sponsored
entities for details.
Does the
service have support for payment delay? See Payment
delay for details.
Does the
service have support for inheritance? See Inheritors
for details.
Does the
service have support for group authentication? See Group
authentication for details.
Does the
service have support for arbiters? See Arbiters
for details.
Must tokens always
be sent encrypted to the service? (If yes, the tokens can be sent
through unencrypted communication channels without any worry about
losing privacy, but are much longer and difficult to type.)
The number of
characters from the token integrity code field which are included in
the token, and compared on the service's side. If this is less than
18, the entire code is used. This is used only for unencrypted
tokens, to reduce their size.
Accepted currency
names. See the available names below.
Asymmetric
encryption key. This is used to encrypt the tokens which are to be
sent to the service. See the required fields below.
Asymmetric signing
key. This is used to verify various signatures created by the
service. The encryption and signing keys must be different. See the
required fields below.
Allowed signature
types. See the available types below.
Service fingerprint
version.
Service fingerprint.
Here are the available
service actions: Create account, Change passphrase, Claim compromised
account., Change service partner, Change sponsored entity, Change
payment delay, Change inheritance trigger timeframe, Change show
payment history, Change inheritor, Login account, Make payment, Setup
subscription.
You must implement the
following actions in your system (all other actions are optional):
Here are the
available service administration actions: Change admin
actions, Stop service, Restart service, Lock service, Unlock service,
Lock account, Unlock account, Lock increase balance, Unlock increase
balance, Increase balance, Decrease balance.
Implementing service
administration actions is optional.
Here are the available
currency names: Gold gram (AUG), Gold ounce (AUO), Silver gram (AGG),
Silver ounce (AGO), Australian Dollar (AUD), British Pound (GBP),
Canadian Dollar (CAD), Chinese Yuan (CNY), Euro (EUR), Japanese Yen
(JPY), New Zealand Dollar (NZD), Swiss Franc (CHF), US Dollar (USD).
Other currency names can be added.
An asymmetric key has the
following required fields:
Key identifier, like
"E1".
RSA public key
exponent, like "10001". Must be a hexadecimal string.
RSA public key
modulus; this must have at least 2048 bits. Must be a hexadecimal
string.
Here are the available
allowed signature types:
Authentication. This
is automatically used if it's necessary.
Authenticate
AxiomaticTokenizer.
Import self service
info. This is automatically used if it's necessary.
Import any service
info.
Root service information,
used only by AxiomaticTokenizer to verify signatures (not to create
tokens), doesn't need token submission weblinks, service actions,
currency names, asymmetric encryption key.
If a given service
validity date is present multiple times in the array with service
information, the service name / seed / ID must be different for all
those array items.
If a given service name
is present multiple times in the array with service information, the
service seed must be the same for all those array items.
If a given service seed
is present multiple times in the array with service information, the
service name must be the same for all those array items.
If a given service ID is
present multiple times in the array with service information, the
service seed must be the same for all those array items.
If a given service name
is present multiple times in the array with service information, the
array item with the validity date closest (and older) than the
current date is used.
Adding
a service
You can easily add a new
service to AxiomaticTokenizer.
Open the source code in a text editor and search for
the following text: "var ServiceInfos". This variable is an
array which contains the information for all supported services.
Copy one of the existing service elements, as a new
service element, and change its information. Pay special attention
to:
Algorithms
The used algorithms are hashes (SHA256), MACs
(MAC-SHA256), asymmetric encryption (RSA).
Pseudo-random number generators and symmetric
encryption have been specifically excluded from the design of
AxiomaticTokenizer.
Radix 32
A byte array is normally represented as text in
radix 32, using the following character set (confusing characters are
not used):
The first character from the text corresponds to the
least significant 5 bits of the byte array, and so on.
Encrypted tokens are represented as text in radix 16
for simpler interoperability (because it has to be reversed by
services).
MAC-SHA256
This MAC is computed using two keys derived from the
shared secret, using two SHA256 hashes. One key is called inner key,
one outer key.
The inner and the outer keys are the SHA256 of
following concatenated information:
The first hash is a SHA256 of following concatenated
information:
The second hash is a SHA256 of following
concatenated information:
Outer key.
The first hash.
Checksum
A checksum provides assurance that a text is not
typed erroneously by a user.
A checksum version "1" is made of the
first 2 characters of the textual representation (in radix 32) of the
SHA256 of the text for which it is computed.
Architecture
Texts and data filling
The letter case for all texts (like names and
passphrases) is insensitive. During comparisons and hashing, all text
is converted to upper case.
All texts are encoded in ASCII-7.
A token is formed by several fields, each two being
separated by a token field separator: ";". A token always
ends with a token field separator. This separator is not included in
any data to hash.
Long texts are always displayed in motes of 3
characters with a mote separator (= a blank space) among them. This
separator is not included in any data to hash.
Time stamp
A time stamp is formed from the following
concatenated textual time information, represented in UTC
coordinates:
Year, 4 digits.
Month, 2 digits.
Day of month, 2 digits.
Hour, 2 digits.
Minute, 2 digits.
Second, 2 digits.
The time stamp makes it possible for the service to
not store the tokens, and not have to compare a token which is being
executed with the previously executed tokens.
Last successfully executed token
The last successfully executed token must be
stored, for each account, by the service in order to know when to
send back to the user the "LastExecuted" execution proof.
When a new token is successfully executed, the previous one must be
overwritten (it may still exist in the history).
The time stamp of the last successfully
executed token must be stored, for each account, by the service in
order to know that the future tokens with a time stamp smaller or
equal with it are not to be executed.
For all the actions affected by group
authentication, all the tokens of the members of the group
(present in the token submission form) must be stored. Also, the
stored time stamp is the biggest one from the stored tokens.
Shared secret generation
A shared secret is the textual representation (in
radix 32) of a passphrase blender.
The passphrase blender version "1" applies
SHA256 20 times iteratively (= over the previous binary hash), to the
MAC-SHA256 of following concatenated information:
Passphrase blender seed.
Service seed.
User account locator.
The MAC's key is the user passphrase.
This algorithm allows the user to use the same
passphrase for all services because the shared secret is different
for each of them (and no service can retrieve the user's passphrase).
Service fingerprint generation
This is executed for the "Generate service
fingerprint" service action.
A service fingerprint version "1" is made
of the first 25 characters of the textual representation (in radix
32) of the SHA256 of following concatenated information:
If the service fingerprint generated by your
AxiomaticTokenizer is the same as the service fingerprint published
by the service itself or by an entity you trust, or by one of your
friends, you can be sure that the service information used to
generate your tokens is correct.
Account locator generation
This is executed for the "Generate account
locator" service action.
An account locator version "1" is made of
the first 12 characters of the textual representation (in radix 32)
of the MAC-SHA256 of the following concatenated information (of the
token):
The MAC's key is the user account name.
This algorithm allows the user to use the same
account name for all services, without the two services being able to
link the accounts to the same user, because the account locator is
different for each of them.
Token integrity code
The token integrity code is the textual
representation (in radix 32) of the MAC-SHA256 of the following
concatenated information:
The MAC's key is the shared secret. For "Create
account" tokens, since there is no existing shared secret, the
new shared secret is used instead.
For "Create account" tokens, since there
is no existing shared secret to guarantee authenticity, the token
integrity code is computed because it ensures that there is no
(accidental) corruption of the token.
Depending on the service, if the token is not
encrypted, only the first X characters (minimum 18) of the token
integrity code are used.
Execution proofs
An execution proof version "AT1" is made
of the first 15 characters of the textual representation (in radix
32) of the MAC-SHA256 of the following concatenated information (of
the token):
The MAC's key is the shared secret.
Reference code format
A reference code is displayed for all tokens. A
reference code has the same version as the associated token.
A reference code version "AT1" is made of
the first 15 characters of the textual representation (in radix 32)
of the MAC-SHA256 of the following concatenated information (of the
token):
The MAC's key is the shared secret.
A token reference code is computed by both the
user's AxiomaticTokenizer and by the service.
When an action has a recipient, the service must
store the reference code in the recipient's account history, together
with the token data.
In the case of a client making a payment to a store,
since a reference code can be computed only by the client who
generated the token, and by the service, and since the online store
also has it in his account's history, the reference code can be used
as a mild proof that a person claiming to have made a payment is
indeed the client. The word "mild" is used here because
this works only as long as the reference code is kept secret by the
three parties.
If you need to quickly locate a token long after it
is generated, keep the token reference code.
Token format
AxiomaticTokenizer implements tokens specifically to
be used for a payment service.
A token is formed by several fields, each two being
separated by a token field separator: ";". This is not
included in the data to hash.
A token may contain white spaces. These must be
removed before the token is processed.
Payment token example
AT1;
MTM; MP; 20081122115157; aliceakula.pub; bobbonkers.pub; NA; AUG; 10;
DET YYM CLR 8G4 SJ5 C9G;
Create account
Fields:
The account locator of the user.
The account locator of the service partner
which is associated to the user's account. If the user didn't
specify a service partner, this field contains "NSP".
The account locator of the sponsored entity
which is associated to the user's account. If the user didn't
specify a sponsored entity, this field contains "NSE".
Payment delay. If the user didn't specify a
payment delay, this field contains "NPD".
Inheritance trigger timeframe.
Show payment history. This is "SH" if
the history has to be shown, and "HH" if it has to be
hidden.
Group authentication. This field contains two
numbers: the first is the required number of present members, the
second is the total number of members of the group.
This token is always asymmetrically encrypted with
the service's public key.
Change passphrase
Fields:
This token is always asymmetrically encrypted with
the service's public key.
Claim compromised account
Fields:
This token is always asymmetrically encrypted with
the service's public key.
See Recover a
compromised service for details.
Change service partner
Fields:
This token may be unencrypted.
Change sponsored entity
Fields:
This token may be unencrypted.
Change payment delay
Fields:
Payment delay. If the user didn't specify a
payment delay, this field contains "NPD". For security
reasons, once the payment delay is set, it can only be increased
(not decreased).
This token may be unencrypted.
Change inheritance trigger timeframe
Fields:
This token may be unencrypted.
Change show payment history
Fields:
This token may be unencrypted.
Change inheritor
Fields:
The account locator of the recipient of the
inheritance.
The number of inheritance shares received by
the recipient account. If this is 0, the inheritor account has to be
deleted from the user's account.
This token may be unencrypted.
See Inheritors for
details.
Login account
Fields:
This token may be unencrypted.
Make payment
Fields:
The account locator of the recipient of the
payment.
The account locator of the arbiter of the
payment. If the user didn't specify an arbiter, this field contains
"NA".
The name of the currency to be paid.
The amount of currency to be paid.
This token may be unencrypted.
Setup subscription
Fields:
The account locator of the recipient of the
payment.
The name of the currency to be paid.
The amount of currency to be paid.
The timeframe between two consecutive payments.
The number of times to make the payment.
This token may be unencrypted.
See Subscriptions for
details.
Change admin actions
Fields:
The account locator of the recipient of the new
administrative actions.
The identifiers of the new administrative
actions, separated by a comma.
This token may be unencrypted.
Stop service
Fields:
This token may be unencrypted.
Restart service
Fields:
This token may be unencrypted.
Lock service
Fields:
This token may be unencrypted.
Unlock service
Fields:
This token may be unencrypted.
Lock account
Fields:
This token may be unencrypted.
Unlock account
Fields:
This token may be unencrypted.
Lock increase balance
Fields:
This token may be unencrypted.
Unlock increase balance
Fields:
This token may be unencrypted.
Increase balance
Fields:
This token may be unencrypted.
Decrease balance
Fields:
This token may be unencrypted.
Encrypted token format
An encrypted token has the following fields
(separated by the token field separator):
A service must expect to receive a token either
encrypted or unencrypted. A token is encrypted if it has exactly 4
fields; the third field is the service's public key identifier.
The RSA padding is PKCS#1 v1.5.
Signed document format
AxiomaticTokenizer can process signed documents.
A sign document has the
following format:
The "**********
Begin AxiomaticTokenizer Document **********" marker which
delimits the beginning of the signed document.
The signed text.
The
"------------------- Begin signature -------------------"
marker which delimits the beginning of the signature of the
document.
"Version=[?];".
The version of the signed document.
"Type=[?];".
The type of the signature.
"FFA=[?];".
This is the name of the algorithm which is used to generate file
fingerprints. For now, only the SHA256 MAC is supported.
"ServiceName=[?];".
The name of the service which created the signed document.
"ServiceSeed=[?];".
The seed of the service which created the signed document.
"KeyId=[?];".
The ID of the asymmetric signing key which was used to sign the
document.
"Time=[?];".
The time when the document was signed.
"Salt=[?];".
A salt used to randomize the signature.
"TextSize=[?];".
The size of the signed text.
"Value=[?]".
The signature value, as a hexadecimal text.
The "***********
End AxiomaticTokenizer Document ***********" marker which
delimits the end of the signed document.
The "[?]"
placeholder can be replaced with any text.
Here are the available
signature types:
Any unknown signature
type is treated as "Authentication".
The time is formed from the following concatenated
textual time information, represented in UTC coordinates:
Year, 4 digits.
Month, 2 digits.
Day of month, 2 digits.
Dash.
Hour, 2 digits.
Minute, 2 digits.
Second, 2 digits.
You can use
AxiomaticTokenizerKeyGen to
sign documents.
Example
********** Begin
AxiomaticTokenizer Document **********
AEB 00F 2B4 25A
DD2 F15 A77 83B 060 553 D23 25C 623 7A7 AA8 5A6 ED9 BA3 FFD E60 ABF B
-------------------
Begin signature -------------------
Version=1;
Type=Authenticate
AxiomaticTokenizer;
FFA=BckSha256;
ServiceName=AxiomaticTokenizer;
ServiceSeed=CO6OS5PKPS57N948OV5J;
KeyId=S1;
Time=20081226-132653;
Salt=C8F 5CF E3F
62C 0D2 CA0 B6;
TextSize=85;
Value=01B A5E
3F3 E76 8D2 BCE C92 E0F BA9 CAF 59C 7A9 80D 91F 9B7 0AF 35F 045 5A8
C51 85A 64D D9D 30C 748 25E 63D 425 9E8 377 ACA E2A 6CE FFA 269 69C
09C 1FD E47 B24 8B2 C97 1A9 CB3 67A FCD C82 2FF B68 23E A17 144 AF2
366 0DA DF2 706 480 A92 498 D44 06B F63 67E 9CC 3E9 8CB 804 652 00B
073 030 40F 6C1 8E7 6CE 79A 717 D6B EBC 15A 918 845 425 5E8 20E 352
835 897 FB7 F1A 646 FC1 603 82B 856 BEB E6A E90 A45 94F E64 8C1 83A
A72 E9F 5EA C7B 098 A40 1B4 CDF 41C 381 995 BBE E5E A7D 874 5DF 0B4
6BC 80D 00E E23 14E EC9 01E 74A 1F9 47B F62 BEF 957 868 028 0A6 F18
B2F 78E 5FA 431 CB8 1D8 851 D32 CEB 755 CA6 FAA 20C BAD 71D 2BC 721
C84 CEA EE7 F71 6B3 7B8 0E7 ADC A7D 5A1 531 149 54C DDC 0BA 0D;
*********** End
AxiomaticTokenizer Document ***********
Weaknesses
Passphrase strength
The security of all tokens depends on how strong the
user's passphrase is and on whether a thief can intercept an
unencrypted token.
If the passphrase is weak, like a single word, a
thief who can intercept a token can use all the known data to
initiate a dictionary attack until he finds that a certain passphrase
generates the token.
Due to the fact that AxiomaticTokenizer is written
in JavaScript and because iterative hashes written in JavaScript are
thousands of times slower than iterative hashes written in native
code (C), very few hash iterations are used when the shared secret is
generated from the user's passphrase. This makes a dictionary attack
much easier.
Therefore, it's critical to use a strong passphrase,
as is specified in the documentation of AxiomaticTokenizer, made from
a memorized part and a written part. Of course, someone might easily
get the written part of the passphrase, but this is virtually
impossible to do remotely. The memorized part makes the written part
useless on its own.
Database
The service must store the shared secrets as they
are given by the users. It's not possible to hash them as passwords
are hashed because the shared secret is not sent by the user every
time he requests an action to be executed.
This means that a thief who can read the (decrypted)
database can steal all the digital currency from all accounts, but
clearly this is the last problem the service has.
A service can recover from such an event. See this
for details.
Choosing seeds
All the seeds (like those for the passphrase and
account name blenders) used by the cryptographic algorithms of
AxiomaticTokenizer in order to make it difficult for an attacker to
precompute the shared secrets associated to user passphrases, and the
account locators associated to account names, are randomly chosen.
Each character from a seed is obtained by rolling
two dice and then looking that up in the dice-character mappings
table from the AxiomaticTokenizer's help.
However, as this standard becomes more widely used,
when a new blender version is created with a new seed, people might
fear that the chosen seed was selected with enough time before its
publication in order to allow precomputation.
Therefore, a seed must be chosen through a public
process, with little time before the new blender version is made
public. Practically, a number of prominent organizations with an
online presence have to be requested by the AxiomaticId Entity to
choose several characters which would be part of the new seed.
Each such organization has to simply roll two dice
several times, and use the dice-character mappings table from the
AxiomaticTokenizer's help to generate the necessary seed characters.
These characters have to be published on the websites of these
organizations, for everyone to see.
Then, the AxiomaticId Entity has to form the new
seed by simply concatenating all the published characters.
Integration tips
Here are some tips for service integration.
Service partners and sponsored entities
The implementation
of service partners and sponsored entities must not hamper the
distributive capabilities of the database.
For this to happen,
the fees for the service partners must not be added to their accounts
at the same time the payments are made.
Instead, they must
be added to a special table and consolidated only once a day / week,
either automatically or manually by the service partners.
User privacy
In order to protect
the privacy of the users, care must be taken.
The service partners
and sponsored entities must not know what users have added them to
their accounts, and how much and who do they pay.
Users must not know
who added them as inheritors.
Token time
For increased safety, a service should consider
invalid a token whose time stamp is smaller with more than 7 days
than the current (service) time, or bigger with more than 5 minutes
(this margin of error is for cases when clocks are desynchronized).
Multiple token execution
There is no need to verify the entire history of
tokens in order to ensure that a token is executed only one time, so
long as the time stamp of the token is verified to be bigger
(not equal) than the time stamp of the last successfully executed
token (time stamp which is stored for each account).
Brute force protection
In order to deter brute force attacks against an
account, a service must process less than 10 ^ 13 tokens / second /
account, be it serial or parallel processing, while returning
"Invalid token integrity code" to the user.
This provides safety for the shortest token
integrity codes for several decades.
AxiomaticTokenizerKeyGen
You can use AxiomaticTokenizerKeyGen (included in
the attached archive) to generate
identities, decrypt and sign data, and generate file fingerprints.
You can also look at the source code included in the
attached archive to see how to decrypt the encrypted tokens using C#.
AxiomaticTokenizerKeyGen uses the AxiomaticId core.
Don't use this program in
production environments.
In order to build AxiomaticTokenizerKeyGen /
AxiomaticId, you need VisualStudio 2008 Pro and Windows Mobile 6 SDK.
You can make a small change to open the solutions in VisualStudio
2005 Standard: open the .sln file in a text editor and change "10"
from the first line ("Microsoft Visual Studio Solution File,
Format Version 10.00") to "9".
Usage
Before you can sign
documents and decrypt encrypted tokens, you have to create a service
initializer (see the "Work \ Create service initializer"
menu).
Open AxiomaticTokenizer
in a text editor and search the array with service informations ("var
ServiceInfos").
In this array, either add
your own service information element or edit an existing one.
Use the "Work \ Clip
encryption public key M" to copy to the clipboard the data which
you have to paste in the "AsymmEncryptionKey.PublicM" field
from the service information element.
Use the "Work \ Clip
signing public key M" to copy to the clipboard the data which
you have to paste in the "AsymmSigningKey.PublicM" field
from the service information element.
Set the "ServiceName", "ServiceSeed",
"AsymmEncryptionKey.Id",
"AsymmSigningKey.Id" fields from the service information
element with the same values that you typed when you created the
service initializer.
Save the edited file with
AxiomaticTokenizer and open it in a webbrowser.
Decrypt encrypted tokens
In AxiomaticTokenizer
choose the service whose information you just edited in
AxiomaticTokenizer and create an encrypted token.
Copy this token (actually
just the token field which contains the encrypted data, the longest
one) from the clipboard and in AxiomaticTokenizerKeyGen click on the
"Decrypt from clipboard" button. The decrypted token will
be put in the visible edit-box.
Verify signatures
In
AxiomaticTokenizerKeyGen type some text in the visible edit-box.
Choose the appropriate
signature type (just leave it with the default value).
Click on the "Sign
to clipboard" button in order to sign the typed text and copy it
to the clipboard.
Go to
AxiomaticTokenizer's help and then click on the "Verify document
signature" link. Now click on the "here" link.
Paste the clipboard
content in the visible edit-box and click on the "Process
document" button. Follow the wizard until the end.
DotNet source code
AxiomaticTokenizerKeyGen uses the AxiomaticId core,
but you can also use pure DotNet to decrypt encrypted tokens. An
example application, RsaKeyGen, is included in the attached archive.
Here is how an encrypted token is decrypted:
RSACryptoServiceProvider rsa = FromRsaKeyParams();
string textToDecrypt = TextToDecryptTextBox.Text;
textToDecrypt = textToDecrypt.Replace( "\n", "" );
textToDecrypt = textToDecrypt.Replace( "\r", "" );
textToDecrypt = textToDecrypt.Replace( " ", "" );
byte[] data = ArrayUtil.HexTextToArray( textToDecrypt );
byte[] decrypted = rsa.Decrypt( data, false );
string decryptedTokenText = ArrayUtil.ArrayToText( decrypted );
The FromRsaKeyParams
is implemented like this:
private RSACryptoServiceProvider FromRsaKeyParams()
{
RSAParameters rsap = new RSAParameters();
rsap.Exponent = ArrayUtil.HexTextToArray( RsaKeyParamETextBox.Text );
rsap.Modulus = ArrayUtil.HexTextToArray( RsaKeyParamMTextBox.Text );
rsap.D = ArrayUtil.HexTextToArray( RsaKeyParamDTextBox.Text );
rsap.DP = ArrayUtil.HexTextToArray( RsaKeyParamDPTextBox.Text );
rsap.DQ = ArrayUtil.HexTextToArray( RsaKeyParamDQTextBox.Text );
rsap.P = ArrayUtil.HexTextToArray( RsaKeyParamPTextBox.Text );
rsap.Q = ArrayUtil.HexTextToArray( RsaKeyParamQTextBox.Text );
rsap.InverseQ = ArrayUtil.HexTextToArray( RsaKeyParamQITextBox.Text );
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)RSACryptoServiceProvider.Create();
rsa.ImportParameters( rsap );
return rsa;
}
Source code details
While you analyze the code, you may realize that you know or you
may see a better way to code a certain feature. But you have to
consider that the target platform for running the code is the world
of mobile browsers, that is, the application must run on PDAs, and
therefore your way of doing things is likely unusable.
Another requirement for the target platform is a touch screen.
This requirement affects the design of the user interface such as to
make it possible to use the fingers as much as possible.
If AxiomaticTokenizer would be written in a high
level language, like C#, not in a scripting language, like
JavaScript, the programming mechanisms would be different. In the
case of JavaScript, the entire program is contained in a single file
in order to make its download easy. Various other programming
mechanisms are simplified due to this constrain and due to the fact
that JavaScript is not type safe. For example, classes are used on a
small scale; of course, the small size of AxiomaticTokenizer makes it
easy to use global declarations.
Code comments
All combo-box items must contain a textual value
which is neither null nor empty. The display text of each item can't
be either null or empty.
The "WipeSensitiveData" function is used
to overwrite any sensitive data found in the RAM (as unallocated
variables). Basically, a large buffer is allocated (and deallocated)
in order to overwrite garbage collected variables.
Browser detection
Detecting the browser on which a JavaScript application runs is
one tough cookie. Many Internet browsers want to fool the visited
websites into thinking that another kind of browser is requesting the
HTML pages.
Here is the code:
function GetHostAppName()
{
var appName = navigator.appName;
appName = (appName != null) ? appName.toUpperCase() : "";
var userAgent = navigator.userAgent;
userAgent = (userAgent != null) ? userAgent.toUpperCase() : "";
if( userAgent.lastIndexOf( "Opera".toUpperCase() ) >= 0 )
{
if( userAgent.lastIndexOf( "PPC".toUpperCase() ) >= 0 )
return "OperaMobile".toUpperCase();
else return "Opera".toUpperCase();
}
else if( appName == "Microsoft Internet Explorer".toUpperCase() )
return "InternetExplorer".toUpperCase();
else if( appName == "Microsoft IE Mobile".toUpperCase() )
return "InternetExplorerMobile".toUpperCase();
else if( userAgent.lastIndexOf( "Safari".toUpperCase() ) >= 0 )
return "Safari".toUpperCase();
else if( userAgent.lastIndexOf( "Mozilla".toUpperCase() ) >= 0 )
{
return "Mozilla".toUpperCase();
}
else return "";
}
Then, we simply need to check the text returned by this function:
function IsBrowserInternetExplorer()
{
return GetHostAppName() == "InternetExplorer".toUpperCase();
}
Portability
The coding in general, and the user interface in particular, had
to be adjusted to provide access to the mobile platforms.
For example, color scheming could be done by dynamically changing
the style sheets (using the document.stylesheets
array),
but this can't be done on mobile browsers. Fortunately, CSS provides
a way out: multiple class names for any HTML element, like <input
type="submit" class="ButtonStyle
ChocolateCream_ButtonStyle"/>
.
Implementation subtleties for the HTML and JavaScript hosts make
debugging difficult at times. For instance, on Internet Explorer
Mobile 6, trying to display or set a display text with a null object
causes an exception, but works in the other Internet browsers.
Another example is, also on Internet Explorer Mobile 6, that a comma
at the end of an array's items generates a null item, but no item in
the other browsers.
Interestingly, despite the large size AxiomaticTokenizer, the
mobile browsers load it and work well with it (although significantly
slower than on the desktop editions of the browsers).
One worry that I had was the speed of the big integer library on
mobile devices. Although the performance of RSA encryption isn't
anywhere near to that of a desktop browser, it's acceptable. For
example, generating an encrypted token on the Opera 9 mobile browser,
on a PDA with a 400 MHz microprocessor, takes about 6 seconds.
Color scheming
The best way to implement color scheming is to do it without
changing the colors of each visual HTML element, and also without
specifying an array with all the HTML elements which need to have a
color scheme (because this would need to be updated as the HTML
elements from the page are added or deleted).
Color scheming is implemented using a CSS feature: multiple class
names for any HTML element, like <input type="submit"
class="ButtonStyle ChocolateCream_ButtonStyle"/>
.
Basically, the colors have been separated from the rest of the CSS
properties, like size or font, in order to allow us to have a single
size of font for all color schemes.
From this point on, all we need to do is change the class name of
the color scheme, that is, simply replace ChocolateCream_ButtonStyle
(which is the default color scheme) with the current color scheme
(for example PaleBlue_ButtonStyle
), like this:
var colorSchemeName = colorSchemeNameArg.toUpperCase();
var prevColorSchemeName = FindPreviousColorSchemeName( className );
className = className.toUpperCase();
if( (prevColorSchemeName != null) && (prevColorSchemeName != "") )
{
prevColorSchemeName = prevColorSchemeName.toUpperCase();
if( className.indexOf( prevColorSchemeName ) >= 0 )
widget.className = className.replace( prevColorSchemeName, colorSchemeName );
}
To change the color scheme of all HTML elements we need to iterate
through all the HTML elements from a page, using the document.all
array. For some reason, it's not possible to iterate using foreach
and it's not possible to get the number of items from the array, but
we can do it with plain indexing and stop when we get a null item:
var i = 0;
while( true )
{
var widget = document.all[ i ];
if( widget == null ) return;
i++;
}
Note that document.all
normally needs a string
parameter, which is the ID of the HTML element to access, but as you
can see here it can also be used to access an HTML element with the
specified index in the array.
Wizard-like user
interface
A wizard-like user interface is the easiest for the
users to work with. At the same time, it is also the most difficult
to develop. Due to the fact that AxiomaticTokenizer is specifically
designed for mobile devices, not desktop computers, a wizard-like
user interface fits best in the small space of the display of such a
device.
Since the entire user interface is contained in a
single file, all HTML elements would be visible when the application
were started, unless they are specifically hidden: <div
class="FrameStyle" id="DebugFrameRow"
style="display: none;">
.
The only HTML elements which must be visible when
the application starts are the frame (<div
class="FrameStyle" id="ApplicationFrameRow">
)
and the element which says that JavaScript is not working (<div
class="ContentRowStyle CenteredStyle
ChocolateCream_ContentStyle" id="NoJavaScriptRow">
).
The latter HTML element is used to simply inform the user that
JavaScript is not working on his computer, and that it is required.
From the moment the application starts, HTML
elements are displayed only programmatically, organized on pages.
Except for the first page, the welcome page, all other pages are
displayed when the user clicks on a button (or otherwise interacts
with the HTML elements).
The pages which are part of a wizard which collects
the data to be used for generating tokens, display a single editable
HTML element in order to guide the user step by step through the
process of filling in the data required to generate a token.
Since AxiomaticTokenizer is a simple application,
only two global buttons are present on a wizard's page, one to move
to the next wizard step, and one to abort the current wizard (and go
back to the main menu).
A wizard is started by calling a method
(StartWizard
) which receives as parameters an array
which describes the wizard's steps / pages, and a JavaScript function
which is executed when the user finishes the wizard (this function
usually generates a token and displays it).
Translation
Translation is very useful for a global application,
particularly for an application whose target is the masses, not
advanced computer users who generally know English.
Because AxiomaticTokenizer is a simple application,
the translation is entirely done when the application starts or when
the user changes the current language, not when a page is displayed.
Before anything, we need to setup the resources
which contain the translated texts, in this case the LocalizedTexts
array. An element of this array contains an ID (by which the search
is done in the array), the language of the display text, what HTML
property to set in code during translation (this is used only for the
automated translation), the actual translated display text, the
formatting data (an array of objects). The position of each
formatting data element is identified in the translated texts in the
usual C style, with indexed placeholders delimited by "{}".
Just like in the case of color schemes, in order to
translate the user interface, we need to iterate through all the HTML
elements, using the document.all
array. We then change
the display text of each element with the translated one. All this is
automatically done by the SetLocalizedGui
function. Here
is how the translation happens when the current language is changed:
var langId = document.all[ "LanguageNameComboBox" ].value;
SetCookie( LangIdCookieName, langId );
SetLocalizedGui( langId );
document.all[ "PageHeaderRow" ].innerHTML = FindCurrentLocalizedText( "Welcome", null );
UpdateComboBoxByIdItem( "ServiceNameComboBox", GenericItemValue_Choose
, FindCurrentLocalizedText( "ChooseServiceNameItem", null ) );
ShowServiceAction();
However, sometimes it may be necessary to manually set the display
text of an HTML element, like when the content of a combo-box is
programmatically populated. In such a case, we need to call the
FindCurrentLocalizedText
function. This will search for
a translated text in the LocalizedTexts
array, for the
current language. This function also accepts formatting data. Here is
how the manual translation of an HTML element is done:
document.all[ "PageHeaderRow" ].innerHTML = FindCurrentLocalizedText( "Welcome", null );
Here is how manual translation with formatting data is done:
var extractedChecksum = GetAccountNameChecksum( accountNameArg );
var accountName = BlendAccountName( accountNameArg, serviceNameArg );
var computedChecksum = ComputeAccountNameChecksum( accountName.toUpperCase() );
if( extractedChecksum.toUpperCase() == computedChecksum.toUpperCase() ) return null;
else return FindCurrentLocalizedText( "InvalidAccountNameChecksum"
, [ extractedChecksum, computedChecksum ] );
Q&A
What's the point of digital checks?
Digital checks have
several very useful properties.
You can write a check on
a computer which is not connected to the Internet, hence your
passphrase and your money are more secure.
You can put a check in
the purchase webform of an online shop. You don't have to send the
check to the payment service, the shop does it and receives back a
confirmation (so, you don't have to prove the payment, and no shop
clerk has to verify the payment - it's all automated). You may also
be able to more efficiently hide your IP address from the payment
service, since you need to access it less.
Checks can be sent to
the payment service through any mean of communication, like SMSs
(axiomatic tokens for payments are generally 95 characters long, so
they fit nicely in the 160 characters limit for SMSs).
Payment services can be
more resilient to DDOS attacks. The service can setup any number of
public proxies which send tokens to the (hidden) service.
How should I choose my passphrase?
It is crucial to choose
it as it is recommended in the documentation of AxiomaticTokenizer.
Can AxiomaticTokenizer be deployed on an existing
online payment service?
Yes. It's a generic system. However, this is only
the client side, the user interface. An online payment service has to
implement the server side, that is, code which parses the incoming
tokens and executes the requested actions in the database.
See this for
details.
May I put a "Make payment" token in the
purchase form of a shopping website?
Yes.
I have seen some proxy websites which send tokens
to the service, to help mitigate DDOS attacks. May I send a token
through such a proxy?
Yes.
I am not sure that my last payment was actually
made. Can I generate a new token with the same payment information?
No! Just resend the same token until you receive an
execution proof from the service. If you receive the "Success"
execution proof, it's guaranteed that the payment was successfully
executed.
DO NOT generate another token with the same
payment information unless you want to make a new payment.
For some reason, a token which I generated an
hour ago didn't reach the service; or it might have, but I am not
sure. How can I ensure that it's ignored if it eventually reaches the
service?
Generate another token (for example, for login) and
send it to the service (until you receive an execution proof from the
service). If you receive from the service either a "Success"
or a "LastExecuted" execution proof, the older token will
not be executed if it reaches the service afterwards.
What information is saved by AxiomaticTokenizer
in order to later access an account?
None. AxiomaticTokenizer is stateless, that is, it
requires no saved information in order to access an account. The user
must remember or store his account names and passphrases.
If a device with AxiomaticTokenizer is lost, all the
accounts of its owner can still be accessed with another device.
A user may choose to have various account names
saved by AxiomaticTokenizer.
How can I not remember a passphrase?
Choose your passphrase
as recommended in the documentation of AxiomaticTokenizer.
If you think it's
necessary to not let anyone get your digital currency, burn or
swallow the paper on which the passphrase is written.
I have a secret account. Because its secret, its
passphrase is not backed up anywhere. How can I make sure that I will
not lose the money I have in it if I forget its passphrase?
For this account, add as
inheritor a public account whose passphrase you have backed up.
If you happen to forget
the passphrase of the secret account, when this enters in inheritance
mode, all the digital currency from it will be moved to your
inheritor public account.
Is it possible for someone to mount a brute force
attack against my passphrase?
Generally, yes because
either you send your tokens to various entities, like online shops
who can mount an attack based on the token integrity code, or you pay
someone who can mount an attack based on the token reference code
(which is saved by the service in the recipient's account).
This is why it's
critical that you choose your passphrases as recommended in the
documentation of AxiomaticTokenizer.
In order to further
protect yourself, always hold most of your digital currency in secret
accounts which have passphrases different than your public accounts.
This way, your tokens don't reach another entity.
There is absolutely no amount of security
(provider-based, user-level hardware, etc...) that can overcome the
user's willingness to hand over access to a social engineering con
artist.
The purpose of AxiomaticTokenizer is to offer a
technological solution to people who want to protect their money
inside the money issuer.
What people choose to do with their money is their
choice, not for AxiomaticTokenizer to police.
The passphrases are not secure enough because I
can't type small and big letters, and special characters like
"!@#$%^&*()".
Having a pool with more characters is not more
secure, but it can create shorter passphrases with the same strength.
The strength of a passphrase is proportional with
the number of combinations which can be made with the pool of
characters from which a passphrase is made.
A given number of combinations can be achieved with
a pool of any number of characters. What makes the difference
is the size of the passphrase.
Having a shorter passphrase might appear more
practical, but a passphrase must also be typed. If only alphanumeric
characters are used, it's much easier to write a passphrase, so this
compensates for the bigger size.
17 characters taken from a pool of 72 characters
give about the same number of combinations as 20 characters taken
from a pool of 36 characters; actually, it's 3 times more
combinations. So, for just 3 characters less the user would have to
use the Shift key, on average, 8.5 times, plus search on the keyboard
the special characters.
Moreover, non alphanumeric characters have a
tendency to create problems with remembering. Sometimes people
accidentally type special characters in their passphrases, even
twice. Capitalization is also a problem.
History
12.01.2009 – Digital signatures created with
AxiomaticTokenizerKeyGen can
be verified.
15.11.2008 – Added infrastructure to verify digital
signatures. In the future, a new service action will allow users to
verify the signatures of small texts signed by services.
09.11.2008 – Added 4 new
administrative actions.
06.11.2008 – Added the service
administration actions. An item in the service actions combo-box,
"Show basic actions" / "Show admin actions",
allows the user to switch between the basic and administrative
actions.
03.11.2008 – The execution proofs are now generalized (=
more may be added, if necessary) and are contained by a combo-box
from which the user can select one to see its meaning.
30.10.2008 – Added a service action to recover
a compromised service.
15.10.2008 – Added a service action to generate the hash
of a service's data.
25.07.2008 – Textual hashes are in general represented in
radix 32.
The service internal name is now a
service seed.
Certain hashes (for
example those for the passphrase blender and for the token integrity
codes) are now MACs. In theory, this is not necessary because the
tokens have a fixed format, but just in case.
01.07.2008 – All tokens have a service ID field to help
with automatic processing. The token submit form can now
automatically select the processing weblink.
31.05.2008 – The Execution
proof is usable for all tokens.
27.03.2008 – Sent the article for publication to
CodeProject.