Skip to content

hugoheden/opaquify

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Opaquify

A small Java project: Create simple opaque (random-looking) strings from clear text strings. The opaquified strings can be deopaquified.

This is much like simple Base64-encoding, but the endcoded strings generated by Opaquify look more random.

This is to be regarded as a toy project. Not available on maven central. It is very similar to Hashids, which you should check out. They have a proper website! Also, check out FriendlyID, etc etc.

Example usage:

Opaquifyer opaquifyer = new Opaquifyer(); // (1)
String opaquified = opaquifyer.opaquify("Opaquify me!"); // (2)
System.out.println(opaquified); // "mek7mop9k49kv9njd5manbsugw" (3)
// ... (4)
String deopaquified = opaquifyer.deopaquify(opaquified); // (5)
System.out.println(deopaquified); // "Opaquify me!" (6)
  1. Create an Opaquifyer instance

  2. Opaquify a string that you feel might need some.. umm "opaquification".

  3. Behold the result.

  4. Other stuff happens, your opaquified token is perhaps passed around here and there

  5. Your opaquified token is now deopaquified back to the original

  6. Indeed, it is back.

Warning: Do not opaquify anything that is even remotely secret. Even though the strings generated by this library may look opaque and scrambled, they should be regarded as fully reversible. As such they offer no security over using the raw input. For some analysis of the Hashids project, see: https://carnage.github.io/2015/08/cryptanalysis-of-hashids. Much of that probably applies here too.

Some notes:

  • The result is encoded using the 36 character alphabet 0-9a-z (0123456789abcdefghijklmnopqrstuvwxyz). There is no way to customize that.

  • Repeated opaquification of the same string yields the same result.

  • But if you need the opaque strings generated by your project to be unique for your project, you can instantiate the Opaquifyer using a.. umm.. "uniquifyer":

Opaquifyer opaquifyer = new Opaquifyer("My project rocks!"); // (1)
String opaquified = opaquifyer.opaquify("Opaquify me!"); // (2)
System.out.println(opaquified); // 1fyhmk7imayvhtmomnsnxy255z2 (3)
  1. The Opaquifyer is instantiated with a "uniquifier": My project rocks!

  2. Opaquify me!

  3. Behold the result - it is different from the result retrieved if no uniquifyer was used.

Use case

  • Your project exposes a list method, where pagination is implemented using page tokens. Your initial idea was to use some raw DB-table ids as page tokens. But then you felt that while these ids are in no way secret, the usage of these ids expose too much internals. You don’t want users of your API to write code that depends on the page tokens being raw ids. You might want to change your code later, right? Better to opaquify the ids, and thus "help" the developers writing client code for your API to not do anything stupid.

  • So you try to opaquify the ids using Base64. But that is just ugly. And the tokens don’t really look very opaque. Anybody can see that they are Base64 encoded strings. There is always going to be some developer that decides to decode your tokens to implement something that they shouldn’t.

  • Therefore, you Googled and landed here. Good! (But this is a toy project, so go checkout Hashids, which will do the job for you.)

Technical goals/non-goals

Goals

  • As little code as possible - use whatever JDK features we can find. (At the time of this writing, we have had limited success - we have about 150 lines of code including comments.)

  • No dependencies on external (non-JDK) libraries

  • Use Java 8. Even though it is old, it is still not end of life (at the time of this writing)

  • Base64 is ugly, don’t generate strings looking like Base64. (Base62 would have been perfect. But to keep the code very compact, we have settled for a 36 character alphabet.)

Non-goals

  • High performance is a non-goal. The execution speed might be slow. It is not intended for inner loops in crypto software, but rather in the context of web-APIs.

  • Production quality is a non-goal. (Nobody is going to maintain the code here for real.)

Comparison with Base64

Original String

Base64 encoded (URL-style)

Opaquified

0

MA

1cwmeolhxbe0rkx1uj40pphphb5

1

MQ

cqm2od7nmyizfqusmjnutl5b81

2

Mg

u4dtw6hq20j69wnq3uimrxmtp4

3

Mw

13uy9fgbqac8cxfhlhuoyvafixd

4

NA

12mmj2306oznvtvtugcyd0sjo75

5

NQ

15v8ph8c2k9b1f2xpduqlzkaouv

6

Ng

60y9h15pk2dx2bx6d917ypwhzp

7

Nw

ht9uu807ll8xt2o543o69huwi2

8

OA

16lo5hh5pr7kxtgorm43o8zx1lk

9

OQ

r5kzg0azz8ca0zeioqtrgdgmfj

10

MTA

y16wsk1vw6zkrwc4l5slx3hdfy

11

MTE

14ophpb8ahdyi26mhunl9dcs5cs

12

MTI

gtc7nzpblnnbtbql85zozfeqyl

13

MTM

1gnp5xmu0ea2r5yzx5bmi1k9hq0

14

MTQ

eub47jeb5khgzvbe6bxacaaq77

15

MTU

18pl9t9y0bkpjsq30vtir0dneys

16

MTY

gzdykne3nhy9i38ysawrqwtsfl

17

MTc

nsnn50u7vsd7a4waeeyu8r42p2

18

MTg

b7fubpjq1qzgaz383qyxfkchmd

19

MTk

1fhd9kbga4uw5kc1jtonsunzngy

10

MTA

y16wsk1vw6zkrwc4l5slx3hdfy

100

MTAw

mj0b2u7dzd7xvkhzr1u527z74j

1000

MTAwMA

95d8ghbo92fl4mpm8jagvsnl1a

10000

MTAwMDA

1fcxqmic1evrvtvchzrwhz2edf4

100000

MTAwMDAw

1ax42p5kcf4sha5ghdju4rhudfd

1000000

MTAwMDAwMA

yb7pp9c68clybjoacctjrp038a

10000000

MTAwMDAwMDA

1f7y7z5dx8brrlm45fh63fdh1ox

100000000

MTAwMDAwMDAw

1haxb4kxheg1mrq4psjkcqp6lnr

1000000000

MTAwMDAwMDAwMA

5fs8jm628cmviyrxxhxza8rdjf

Base64 encoding might sometimes be too unopaque, right?

TODOs

(Well probably never be done?)

  • Hmm, naming is weird. Also, consider spelling Opaquifyer as Opaquifier, i.e. i instead of y. I mean, we do use uniquifier (with an i).

  • Support encoding radix 62, if that can be done in a very compact way

About

Java: Make opaque strings for use as pagination tokens

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages