Obol Howto and FAQ
[ Main Page ]
This is a collection of various Obol tips and frequently asked questions
(with answers).
Color legend of code and examples:
Using the toplevel interpreter
The Obol runtime provides a simple toplevel to the interpreter.
The minimal (Java) code necessary to invoke it is:
import parser.ObolParser;
...
ObolParser.getInstance(System.in).parse("toplevel");
|
To avoid the frustration of endless careful typing, it is strongly
recommended to use a readline wrapper such as the rlwrap command
line tool, e.g
% rlwrapper java toplevel
Config:
Random-number generator: securely initialized
Cryptographic libraries: JCE, BouncyCastle, Cryptix
Registered Formats: serialization, spki
Languages available for eval: python (Jython)
[Obol 0]>
|
Writing a generated key to a file
This will generate and write a key to a file, using the current format.
1 (generate key shared-key AES 128)
2 (believe output-file "my-key.key" file.out)
3 (send output-file key)
|
Use e.g. [format spki] before send to use a specific
storage format.
If a secret key is written to the file, the runtime may print a warning
which you are free to ignore according to your security policy.
Reading a key from a file
There are two ways. First, using load:
(believe key (load "my-key.key") shared-key ((alg AES)))
|
The alg property can be omitted if the key was stored using a
information-rich format (such as serialization), as the runtime can
derive the property from the data. However, it is prudent to state ones
assumptions, so do specify it.
The second way, uses receive:
1 (believe input-file "my-key.key" file.in)
2 (receive input-file *key)
3 (believe key *key ((type shared-key)(alg AES)))
|
As with using load, the explicity typing (line 3) may be omitted if
the format used contains typing information, but should be used to avoid
confusion.
The former, using load, can only load a single key at a time, but
it is very clear what's going on.
The latter, using receive, can load any number of keys or data, as
the read file is treated as a received message.
Disabling Ordering a.k.a. Using Pool-Mode Unordered Matching
Controversy ahead. This is a experimental mode in which we turn off the
assumption that the order of message components within a message matters.
In effect, a message (a, b) is identical to (b, a). Yes, it is perfectly
possible to write undecidable Obol programs with this. On the other hand,
protocols that work under in this mode should prove to be rather robust.
We don't know.
So far, it seems that assuming a particular ordering is simply an
optimization.
- A:
-
1 [self "localhost:9001" "spki" ((match-ordering unordered))]
2 (believe *1 ((type shared-key)(alg aes)))
3 (receive *a *1 (decrypt *1 "foo" *2))
4 [print "Should not be foo: " *2]
- B:
-
1 [format spki]
2 (believe a "localhost:9001" host)
3 (generate k shared-key aes 128)
4 (send a k (encrypt k "bar" "foo"))
|
Trouble combining encryption and signatures
If signatures and encryption is naively combined, verification will
typically fail (this depends on the undelying cipher-mode used).
This is due to randomization of the encryption, and that Obol doesn't
automatically cache encryption results -- the latter is an explicit design
choice, as correctly determining when to safely use cached results seems to
be hard.
For example (kp is an keypair, k some symmetric-key):
1 (believe *s (sign (private-key kp) (encrypt k "foo")))
2a (verify (public-key kp *s) (encrypt k "foo"))
|
This cannot possibly work, since the ciphertext the signature is on is
not kept, and the next encryption will yield a different ciphertext due to
randomized.
Instead, the ciphertext must be manually cached:
1 (believe *c (encrypt k "foo"))
2 (believe *s (sign (private-key kp) *c))
3 (verify ((public-key kp) *s) *c)
|
This is not an Obol issue, but a consequence of cipher construction in
general.
Issuses with generate eval python and anonymous variables
Python/Jython is an in-fix programming language, so anonymous variables can
cause trouble. Why? Because the Python/Jython interpreter thinks the
initial asterisk is a multiplication.
Instead of automatically rewriting the python code (which is a pandorax box
if I ever saw one), the Obol runtime simply silently rewrites any symbol
arguments before they get turned into variables for the Python/Jython
interpreter.
This means that the python code must use the symbol name without the
asterix-prefix.
So, instead of this:
(generate *p eval jython "1+*x" *x)
|
Do this:
(generate *p eval jython "1 + x" *x)
|
This only applies to in-fix languages (currently Pyton/Jyton).
The supported Lisps have none of the above issues, so no silent rewriting is
necessary:
(generate *q eval lisp "(* 2 *x)" *x)
|
|