How to generate a UUID via a cryptographically secure random number generator in Apigee

Is there a way to generate a true random UUID in Apigee? I'm trying to generate a random UUID in javascript but am being told by our Security guys that Math.random isn't truly random. Is there a way to generate a truly random number without going into a Node back end?

Solved Solved
2 13 4,534
1 ACCEPTED SOLUTION

EDIT (2021 February)

To get a true random uuid, use the static function createUuid from within a message template. Like this:

<AssignMessage name='AM-Uuid'>
  <AssignVariable>
    <Name>my-uuid</Name>
    <Template>{createUuid()}</Template>
  </AssignVariable>
</AssignMessage>

The UUID is generated using a cryptographically strong pseudo random number generator (PRNG).

OLD ANSWER - Still works but not necessary.

The Javascript versions may work just fine for your purposes. If you expect to run at higher load and concurrency, you will want to use Java.

I've built a simple, re-usable Java callout that uses java.security.SecureRandom to generate random numbers, and random UUIDs. Find it at https://github.com/DinoChiesa/ApigeeEdge-Java-SecureRandom.

Configure it like this:

<JavaCallout name='Java-PRNG-UUID'>
  <ClassName>com.dinochiesa.edgecallouts.SecureRandomCallout</ClassName>
  <Properties>
    <Property name='algorithm'>SHA1PRNG</Property>
    <Property name='output-type'>uuid</Property>
  </Properties>
  <ResourceURL>java://edge-java-callout-prng.jar</ResourceURL>
</JavaCallout>

This callout uses java.security.SecureRandom to generate UUIDs. It caches the SecureRandom (which is thread safe) so that the generation of new UUIDs will be fast at high concurrency.

It is ready to use; you do not need to build or compile it, in order to use it. But the source code is there so you can change or extend it as you need.

Apache 2.0 license.

View solution in original post

13 REPLIES 13

@Dave Pickard

See similar questions asked here & here. Keep us posted if any.

Thanks Anil. I think my title probably wasn't the best (now updated). I'd seen the first link but I'm told that Math.random() isn't cryptographically secure. The messageid I guess could be an option although it would depend on how it was generated.

Does the use dictate the need to be cryptographically secure? You can generate RFC compliant UUIDs in pure javascript. I only ask because I've experienced first hand where the security folks don't always take the time to consider the risk and simply respond with the standard answer.

@Dave Pickard ,

Apigee javascript object model supports some crypto functions, I had given a try using best of both to generate secure random id, code below,

try {
    var makeGUID = function makeGUID() {
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
        return v.toString(16);
      })
    }
    //get values to use with hash functions
    // get salt from KVM / flow variable / hardcode here
    var salt = context.getVariable("salt") || 'SomeHardCodedSalt';
    var guid = makeGUID();
    print(guid);
    var unhashed_token = "";
    var _timeNow = Number(context.getVariable('system.timestamp'));
    print(_timeNow);
    var now = crypto.dateFormat('YYYY-MM-DD HH:mm:ss.SSS','PST', _timeNow); 
    print(now);
    unhashed_token = "|" + now + "|" + guid;
  
    //generate a hash with the unhashedToken:  
    var sha512 = crypto.getSHA512();
    sha512.update(salt);
    sha512.update(unhashed_token);


    //convert to base64
    var base64_token = sha512.digest64(); 
    
    // set headers
    print("orginal guid :" + guid);
    print("secure random id :" + base64_token);


} catch(e) {
    throw 'Error in Javascript';
}

Hope it helps, keep us posted if any.

Thanks @Anil Sagar - I'll have a look at that.

@Dave Pickard ,Make sure you change the salt value in above code. You can read it from KVM / flow variable / hard code same to some other value.

Dear Team,

It was recommended in apigee videos to use java for complex crypto . Why we dont try in java?

PS: Current JDK 7/8 currently support almost all types of crypto

@Sujith Mathew , Yep You can use Java too. Yes, It's recommended one. Above solution is useful for trial users, pro & smb pricing plans. Java is supported only for Enterprise edge customers.

Ad you mentioned get salt from KVM. How to do that?

EDIT (2021 February)

To get a true random uuid, use the static function createUuid from within a message template. Like this:

<AssignMessage name='AM-Uuid'>
  <AssignVariable>
    <Name>my-uuid</Name>
    <Template>{createUuid()}</Template>
  </AssignVariable>
</AssignMessage>

The UUID is generated using a cryptographically strong pseudo random number generator (PRNG).

OLD ANSWER - Still works but not necessary.

The Javascript versions may work just fine for your purposes. If you expect to run at higher load and concurrency, you will want to use Java.

I've built a simple, re-usable Java callout that uses java.security.SecureRandom to generate random numbers, and random UUIDs. Find it at https://github.com/DinoChiesa/ApigeeEdge-Java-SecureRandom.

Configure it like this:

<JavaCallout name='Java-PRNG-UUID'>
  <ClassName>com.dinochiesa.edgecallouts.SecureRandomCallout</ClassName>
  <Properties>
    <Property name='algorithm'>SHA1PRNG</Property>
    <Property name='output-type'>uuid</Property>
  </Properties>
  <ResourceURL>java://edge-java-callout-prng.jar</ResourceURL>
</JavaCallout>

This callout uses java.security.SecureRandom to generate UUIDs. It caches the SecureRandom (which is thread safe) so that the generation of new UUIDs will be fast at high concurrency.

It is ready to use; you do not need to build or compile it, in order to use it. But the source code is there so you can change or extend it as you need.

Apache 2.0 license.

Hi @dchiesa1 , @anilsr ,

Regarding the way of how the  the static function createUuid works


The UUID is generated using a cryptographically strong pseudo random number generator (PRNG).


Based on my observation this function generates v4 UUID, though I haven't found any related information of this behaviour in the documentation.

Is it possible to complete the documentation with the exact information of what version/variant of uuid is generated by the referred function?

Thank you in advance,

Marcello

Yes, in fact the createUuid function is implemented as a wrapper on the java.util.UUID.randomUUID() method, which returns a v4 UUID. That is not part of the documentation.  I'll see if the team will update the doc to clarify that the output is a v4 UUID. 

 

Great, thank you very much for your quick response!