Difference between revisions of "LlGenerateKey"

From Second Life Wiki
Jump to navigation Jump to search
m (moved LlGenerateKey2 to LlGenerateKey over redirect)
m
 
(12 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{LSL_Function
{{LSL_Function
|func=llGenerateKey
|func=llGenerateKey
|func_desc=Generates a key using Type 3 (MD5) UUID generation to create a unique key using region-name, object-key, service and variable.
|func_desc=Generates a key using [http://en.wikipedia.org/wiki/UUID#Version_5_.28SHA-1_hash.29 Version 5 (SHA-1 hash)] [[UUID]] generation to create a unique key.
|return_type=key
|return_type=key
|return_text=The generated key
|Return_text=generated.
|p1_type=string|p1_name=service|p1_desc=The service, object, function, or whatever else this key may represent.
|caveats=
|p2_type=string|p2_name=variable|p2_desc=Any variable(s) relevant to the service that uniquely distinguish it.
*The specific UUID version is an implementation detail that has changed in the past and may change again in the future. Do not depend upon the UUID that is returned to be Version 5.
|mode=user
*As the UUID produced is versioned, it should never return a value of [[NULL_KEY]].
|cat1=Examples
|mode
|cat2=Library
|examples=
|examples=In a two-prim linked-set put the following script (adding generateKey where noted) into the child-prim:<lsl>integer requestID = 0;
<source lang="lsl2">
default
{
    touch_start(integer num_detected)
    {
        // avatar touching
        key avatarKey = llDetectedKey(0);
        string avatarName = llKey2Name(avatarKey);


// Add generateKey here!!
        // key of the owner
        key owner = llGetOwner();


default {
        // generated random key
    touch_start(integer x) {
        key random = llGenerateKey();
         llMessageLinked(
 
            LINK_ROOT,
         // number of objects inside the same prim
            1234,
        integer numberOfObjects = llGetInventoryNumber(INVENTORY_OBJECT);
            "I am a request",
            generateKey("echo", (string)requestID++)
        );
    }


    link_message(integer x, integer y, string msg, key id) {
        if (numberOfObjects)
        if (y == 1234)  
        {
             llOwnerSay("Request: " + (string)id + " = " + msg);
            // name of first object sorted by name inside the prim's inventory
     }
            string itemName = llGetInventoryName(INVENTORY_OBJECT, 0);
}</lsl>And the following script in the root-prim:<lsl>default {
   
    link_message(integer x, integer y, string msg, key id) {
            llGiveInventory(avatarKey, itemName);
        if (y == 1234) // Echo, send straight back
             llInstantMessage(avatarKey, "Your transaction key is '" + (string)random + "'.");
             llMessageLinked(x, y, msg, id);
      
            llInstantMessage(owner, "Transaction record:\n"
                + "receiver: " + avatarName + " (" + (string)avatarKey + ")\n"
                + "item: " + itemName + "\n"
                + "transaction key: " + (string)random);
        }
        else
        {
            // PUBLIC_CHANNEL has the integer value 0
             llSay(PUBLIC_CHANNEL, "No items to give away, sorry!");
        }
     }
     }
}</lsl>Simply touch the child-prim to use, enjoy!
}}
= Implementation =
<lsl>key generateKey(string service, string variable) {
    return (key)llInsertString(
        llInsertString(
            llInsertString(
                llInsertString(
                    llMD5String(
                        "secondlife://" + llGetRegionName()  + "/" +
                            (string)llGetKey() + "/" +
                            (string)llGetLinkNumber() + "/" +
                            llGetScriptName() + "/" +
                            service + "/" + variable,
                        0 // This is reserved by specification, will
                          // be increased with new/different versions.
                    ),
                    8,
                    "-"
                ),
                13,
                "-"
            ),
            18,
            "-"
        ),
        23,
        "-"
    );
}</lsl>
= Optimisation =
Instead of always calling [[llGetRegionName|llGetRegionName()]], [[llGetKey|llGetKey()]], [[llGetLinkNumber|llGetLinkNumber()]], and [[llGetScriptName|llGetScriptName()]], you may wish to cache their return values into a <code>uri</code> variable, and only dynamically add the service and variable parameters each-time. Remember to update this variable when you know it's components will have changed, using the [[changed|changed()]], [[on_rez|on_rez()]], and/or [[attach|attach()]] events.
Here is an example of the caching version of the function:
<lsl>string uri;
key generateKey(string service, string variable) {
    if (uri == "")
        uri =  "secondlife://" + llGetRegionName()  + "/" +
            (string)llGetKey() + "/" +
            (string)llGetLinkNumber() + "/" +
            llGetScriptName() + "/";
    return (key)llInsertString(
        llInsertString(
            llInsertString(
                llInsertString(
                    llMD5String(
                        uri + service + "/" + variable,
                        0 // This is reserved by specification, will
                          // be increased with new/different versions.
                    ),
                    8,
                    "-"
                ),
                13,
                "-"
            ),
            18,
            "-"
        ),
        23,
        "-"
    );
}
}
 
</source>
integer counter = 0;
|cat1=Key
default {
|cat2
    state_entry() {
|history=*Inspired by the library function [[generateKey]].
        llSetTimerEvent(10.0);
*Changed from using [http://en.wikipedia.org/wiki/UUID#Version_3_.28MD5_hash.29 Version 3 (MD5 hash)] to [http://en.wikipedia.org/wiki/UUID#Version_5_.28SHA-1_hash.29 Version 5 (SHA-1 hash)]. Date of this change is unknown.
    }
}}{{LSLC{{#var:lang}}|Encryption|llGenerateKey}}
 
    on_rez(integer x) { uri = ""; }
    attach(key id) { uri = ""; }
    changed(integer changes) {
        if (changes & (CHANGED_REGION | CHANGED_INVENTORY)) uri = "";
    }
 
    timer() {
        llOwnerSay("Random key of the moment is \"" + (string)generateKey("counter", (string)(counter++)) + "\"");
    }
}</lsl>
 
{{LSLC|Examples}}

Latest revision as of 00:30, 22 January 2015

Summary

Function: key llGenerateKey( );

Generates a key using Version 5 (SHA-1 hash) UUID generation to create a unique key.
Returns the key generated.

Caveats

  • The specific UUID version is an implementation detail that has changed in the past and may change again in the future. Do not depend upon the UUID that is returned to be Version 5.
  • As the UUID produced is versioned, it should never return a value of NULL_KEY.

Examples

default
{
    touch_start(integer num_detected)
    {
        // avatar touching
        key avatarKey = llDetectedKey(0);
        string avatarName = llKey2Name(avatarKey);

        // key of the owner
        key owner = llGetOwner();

        // generated random key
        key random = llGenerateKey();

        // number of objects inside the same prim
        integer numberOfObjects = llGetInventoryNumber(INVENTORY_OBJECT);

        if (numberOfObjects)
        {
            // name of first object sorted by name inside the prim's inventory
            string itemName = llGetInventoryName(INVENTORY_OBJECT, 0);
    
            llGiveInventory(avatarKey, itemName);
            llInstantMessage(avatarKey, "Your transaction key is '" + (string)random + "'.");
    
            llInstantMessage(owner, "Transaction record:\n"
                + "receiver: " + avatarName + " (" + (string)avatarKey + ")\n"
                + "item: " + itemName + "\n"
                + "transaction key: " + (string)random);
        }
        else
        {
            // PUBLIC_CHANNEL has the integer value 0
            llSay(PUBLIC_CHANNEL, "No items to give away, sorry!");
        }
    }
}

Deep Notes

History

Signature

function key llGenerateKey();