Closed madanprabhud closed 4 years ago
Hello, I just saw this, and figured I might offer valid comment about this.
My first thought was that this was due to initial loading of some libraries required to actually produce the token, and I was right. Your observed increased time was due to initial loading of various required libraries in JVM. The crypto libraries cary some weight, and require some "loading" time. (Some other parts may have small problem also.)
Please note that this is just for the first time in the running JVM.
If you are to load required parts in the static
block, or before actually creating token you would have millisecond time for creation.
The easiest way to validate this is to wrap the content from the main
method block in a for
loop, with few (i.e. 10
) iterations. Even in the second you should save same or smaller time for token creation.
If you are to increase the iteration to 100
or 1000
you might get sub-millisecond time for token creation and parse time.
P.S. Another point, that may not be needed for your case, is that there is better way to do benchmarking in Java, using excellent JMH project.
Hello, I just saw this, and figured I might offer valid comment about this.
My first thought was that this was due to initial loading of some libraries required to actually produce the token, and I was right. Your observed increased time was due to initial loading of various required libraries in JVM. The crypto libraries cary some weight, and require some "loading" time. (Some other parts may have small problem also.)
Please note that this is just for the first time in the running JVM.
If you are to load required parts in the
static
block, or before actually creating token you would have millisecond time for creation.The easiest way to validate this is to wrap the content from the
main
method block in afor
loop, with few (i.e.10
) iterations. Even in the second you should save same or smaller time for token creation. If you are to increase the iteration to100
or1000
you might get sub-millisecond time for token creation and parse time.P.S. Another point, that may not be needed for your case, is that there is better way to do benchmarking in Java, using excellent JMH project.
Hi zbilijic,
Thanks for your quick resolution.
Iterated for multiple times also, duration for token creation seems to be quite higher. Kindly just the best way of creating token for encrypted v1.
Token Creation Time -- 11871
Token Creation Time -- 76723
Token Creation Time -- 35702
Token Creation Time -- 62972
Token Creation Time -- 17359
Even, we are planning to use as REST service for login authentication with PASETO token as response. So, we can't iterate for the single logon use.
So, Kindly share some code-snippets for the faster token creation.
My Testing OS is Linux.
Is it due to the Secure Random functionality?
If so, how can handle more effectively?
I did not want to expand my comment too much, although several things are left open.
To begin with (as I mentioned), this is some code based on your example:
import dev.paseto.jpaseto.Pasetos;
import dev.paseto.jpaseto.lang.Keys;
import javax.crypto.SecretKey;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class JPasetoExample {
private static final SecretKey SHARED_SECRET = Keys.secretKey();
public static void main(String[] args) {
System.out.print("Secret Key in Base64 -- " + Base64.getEncoder().encodeToString(SHARED_SECRET.getEncoded()) + "\n");
// generate multiple tokens
for (int i = 0; i < 100; i++) {
long start = System.nanoTime();
String tokenString = createToken();
long end = System.nanoTime();
System.out.printf("[%d] Token [%s] Creation Time -- %d\n", i, tokenString.substring(0, 10), TimeUnit.MILLISECONDS.convert(end - start, TimeUnit.NANOSECONDS));
}
}
public static String createToken() {
Instant now = Instant.now();
String token = Pasetos.V1.LOCAL.builder()
.setSharedSecret(SHARED_SECRET)
.setIssuedAt(now)
.setExpiration(now.plus(1, ChronoUnit.HOURS))
.setAudience("blog-post")
.setIssuer("https://developer.okta.com/blog/")
.claim("1d20", new Random().nextInt(20) + 1)
.compact();
return token;
}
}
Running this example code snippet, I have following results:
Secret Key in Base64 -- GlZnbYM9N6xkcUPGaN4loeoDSckEdGpGB2o9LxoXIFE=
[0] Token [v1.local.d] Creation Time -- 1034
[1] Token [v1.local.p] Creation Time -- 4
[2] Token [v1.local.V] Creation Time -- 5
[3] Token [v1.local.N] Creation Time -- 2
...
[96] Token [v1.local.T] Creation Time -- 0
[97] Token [v1.local.X] Creation Time -- 0
[98] Token [v1.local.o] Creation Time -- 1
[99] Token [v1.local.j] Creation Time -- 1
This class was just added in "intergration-tests" project of paseto-toolkit/jpaseto
.
In order to know exactly why you have the issue, you should share whole example project that you use, in order for someone to be able to try to reproduce locally in entirety.
By only providing example that you did, I could only try that one, and can say that it works. The first time token is created will be slow, however each subsequent should take around single millisecond.
It's due to the secure random. Installed haveged and now i got the tokens created at only 700 milliseconds.
Many Linux distros (mostly Debian-based) configure OpenJDK to use /dev/random for entropy.
/dev/random is by definition slow (and can even block).
From here you have two options on how to unblock it:
Improve entropy, or Reduce randomness requirements. Option 1, Improve entropy
To get more entropy into /dev/random, try the haveged daemon. It's a daemon that continuously collects HAVEGE entropy, and works also in a virtualized environment because it doesn't require any special hardware, only the CPU itself and a clock.
On Ubuntu/Debian:
apt-get install haveged update-rc.d haveged defaults service haveged start On RHEL/CentOS:
yum install haveged systemctl enable haveged systemctl start haveged Option 2. Reduce randomness requirements
If for some reason the solution above doesn't help or you don't care about cryptographically strong randomness, you can switch to /dev/urandom instead, which is guaranteed not to block.
To do it globally, edit the file jre/lib/security/java.security in your default Java installation to use /dev/urandom (due to another bug it needs to be specified as /dev/./urandom).
Like this:
securerandom.source=file:/dev/./urandom Then you won't ever have to specify it on the command line.
@madanprabhud Thanks for following up!
Maybe it's worth adding a note about this in our docs? What distro are you using, and which OpenJDK (vendor and version)?
@bdemers
I though to convey the same. Kindly keep this tweak for better performance as note in the documentation.
Please find my Distro and JVM version as follows.,
Distributor ID: LinuxMint Description: Linux Mint 19.3 Tricia Release: 19.3 Codename: tricia
openjdk version "11.0.8" 2020-07-14 OpenJDK Runtime Environment (build 11.0.8+10-post-Ubuntu-0ubuntu118.04.1) OpenJDK 64-Bit Server VM (build 11.0.8+10-post-Ubuntu-0ubuntu118.04.1, mixed mode, sharing)
One more info: in jpasteo example at https://github.com/oktadeveloper/okta-jpaseto-example/blob/master/src/main/java/com/okta/example/JPasetoExample.java
What's the need to specifying the Asymmetric key with symmetric key in only at parsing without configure anything at token creation time?
Kindly explain to me if anything wrong in my understanding.
I’ll try to improve the example. But the TL;DR is a parser instance can parser all types of token (if/when the keys are configured) but a token builder can only create a single type of token.
In normal usage you likely will only be dealing with a single token type
jwt is faster and more secure than papeto i swtiched recently works good I also pay $2 per month for devs who work at jwt to improve perfomance of database queriing
We are evaluating the wonderful jpaseto library for one of our project. Kindly find our observation and their respective code.
Our primary concern about the 1 minute for token creation and we can't afford this at our production (Time mentioned in Milliseconds).
Kindly check the primary testing code and give your suggestion if any improvements.
Our Testing System Configuration : system HP ProBook 440 G6 processor Intel(R) Core(TM) i7-8565U CPU @ 1.80GH memory 8GiB SODIMM DDR4 Synchronous 3200 MHz memory 256KiB L1 cache memory 1MiB L2 cache
`public class JPasetoExample { private static final SecretKey SHARED_SECRET = Keys.secretKey();
}`
Output :
Secret Key in Base64 -- JdhPEhZ2B87HmbJ+6JOoA+uAMFnZEKqQbMOSWXdUFQo= Token Creation Time -- 91076 Paseto token: v1.local.Dgw158XSwr7sxzFbtkXfoOIFu37_gxEUNX5D6KLwhMdCqlwQCBJaFJyMDPPpSXEhHMWxLDj49vCLzvqS-e0K4bwJpmz90WrRNpESkjP1DFoisJUu5KQpHgZ8xjsgrxLgfyQoPIBLcZ61nTpDFmb6UdLQQQmqy21_vMELM_sSpv-1Su-IUtKyvEfgwkAevIW7-vAO_AdHJ1TnFFySRzqhmRjKbpKs1qXqFBLP4l2rM9hSUDcJeZBaXqwi1OxshKlND2LEbk2SL79paaSfC-doDblbbhmGrbs3z9HoyKdKawJnwLQuXKi1 Token Parse Time -- 21 Token Claims: aud: blog-post 1d20: 7 iss: https://developer.okta.com/blog/ exp: 2020-08-14T08:39:18.594777+00:00 iat: 2020-08-14T07:39:18.594777+00:00 Token Claims Traversal -- 1 Audience: blog-post Token get Audience -- 0 1d20 rolled: 7 Token Custome Claim -- 0 Token Parse Time with Requirements -- 2