Difference between revisions of "LlXorBase64StringsCorrect"

From Second Life Wiki
Jump to navigation Jump to search
m
m
Line 7: Line 7:
|p1_type=string|p1_name=str1|p1_desc=Base64 string
|p1_type=string|p1_name=str1|p1_desc=Base64 string
|p2_type=string|p2_name=str2|p2_desc=Base64 string
|p2_type=string|p2_name=str2|p2_desc=Base64 string
|func_footnote={{LSLP|str2}} repeats if it is shorter than {{LSLP|str1}}. If the inputs are not Base64 strings the result will be erratic.<br/> Be sure to read the [[#Cryptography|Cryptography]] section before designing a cryptographic algorithm.
|func_footnote={{LSLP|str2}} repeats if it is shorter than {{LSLP|str1}}. If the inputs are not Base64 strings the result will be erratic.
|func_desc=Correctly performs an exclusive or on two Base 64 strings.
|func_desc=Correctly performs an exclusive or on two Base 64 strings.
|return_text=that is a Base64 XOR of {{LSLP|str1}} and {{LSLP|str2}}.
|return_text=that is a Base64 XOR of {{LSLP|str1}} and {{LSLP|str2}}.
Line 13: Line 13:
|caveats=
|caveats=
* During the conversion to a byte array the last <code>(bitcount % 8)</code> are discarded from both {{LSLP|str1}} and {{LSLP|str2}}. See [[#Implementation|Implementation]] for details.
* During the conversion to a byte array the last <code>(bitcount % 8)</code> are discarded from both {{LSLP|str1}} and {{LSLP|str2}}. See [[#Implementation|Implementation]] for details.
* Considers any null encountered in {{LSLPT|str2}} to mark the end of {{LSLPT|str2}}.
|constants
|constants
|examples=<lsl>default
{
    state_entry(){
       
        // Use a HARD password ! with caps nocaps numbers and symbols !
        string pass = "P4s5Wo_rD";
       
        string data = "I am some ver important data.";
       
        // Enccrypting the data:
        string crypt = llXorBase64StringsCorrect(llStringToBase64(data), llStringToBase64(pass));
       
        // Say the mess you made to Owner
        llOwnerSay(crypt);
       
        // DeCrypting the data and say back to owner:
        llOwnerSay(llBase64ToString(llXorBase64StringsCorrect(crypt, llStringToBase64(pass))));
       
    }
}</lsl>
<lsl>
// Stronger encryption - generates a random encrypted string.
//safe character set
string ASCII = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
//convert integer to characters
string chr(integer i)
{
    return llGetSubString(ASCII, i, i);
}
//for generating a random string.
string salt(integer amount) {
    string salt = "";
    integer i;
    //for length of salt , generate characters
    for(i = 0; i < amount; i++) {
        salt += chr((integer)llFrand(llStringLength(ASCII)));
    }
    return salt;
}   
default
{
    touch_start(integer n) {
        //generates a random salt to add to the string.
        //put salt on the end so that even if the data is corrupted by SVC-6362, it is unimportant data
        string data = "I am some very important data." + salt((integer)llFrand(5)+ 5);
        string pass = "password";
        // Encrypting the data:
        string crypt = llXorBase64StringsCorrect(llStringToBase64(data), llStringToBase64(pass));
        // Say the mess you made to Owner
        llOwnerSay(crypt);
        // DeCrypting the data and say back to owner: Remember to remove the salt when needed ;)
        llOwnerSay(llBase64ToString(llXorBase64StringsCorrect(crypt, llStringToBase64(pass))));
    }
}
</lsl>
|helpers
|helpers
|also_functions
|also_functions
|also_events
|also_events
|also_tests
|also_tests
|also_articles=
|also_articles
|notes=
===Implementation===
The XOR is performed by converting each Base64 strings {{LSLP|str1}} and {{LSLP|str2}} into a byte arrays and then XORing the two byte arrays. Finally converting the resulting byte array back into Base64 and returning it to the user.
 
However during the conversion to byte arrays the last (bitcount % 8) are discard. LSL treats Base64 strings as 8-bit byte arrays, not arrays of 6-bit bytes.
 
===Cryptography===
 
While the information provided in this section is by no means exhaustive, it should give the reader enough information that they can ask the right questions and guide their future reading. Writing cryptographic algorithms should not be attempted without an understanding of cryptography as the results may otherwise be disastrous.
 
In cryptography, a ''secret'' is a bit of input information that is used to transform the cryptographic algorithm. The ''secret'' is not mutated with subsequent runs of the algorithm. A ''seed'' is also used to transform the algorithm but unlike the ''secret'' it does mutate; the method of mutation is part of the algorithm.
 
To effectively use a secret and a seed you need to keep secret at-least two of the following: '''1)''' the algorithm, '''2)''' the seed, or '''3)''' the secret.
 
Believe it (or not) that keeping your algorithm secret will not protect you. The attack vectors that can be used against XOR algorithms require little or no knowledge of the algorithm. The best protection is a strong algorithm that uses multiple secrets/seeds. In this way you can still satisfy the prior precondition by interpreting the numbered items as categories. Keep in mind how the secrets and seeds are used, an attacker need not determine the secrets, only intermediate static values and the relationship between intermediate values for the algorithm to be broken. Do not give the attacker secrets and seeds that render blocks of living code, static. The more information provide to the attacker, the simpler your algorithm becomes.
 
====Best Practices====
 
As a cryptographic technique, XOR is weak and there are several attacks that can be leveraged to determine the XOR inputs. Depending upon how the secrets are used cracking a single message could expose the input secrets, resulting in the derived algorithm being broken.
 
Keep your secrets secret. Use a seeded trap door function to shake up the bits of the secret before using with the XOR and change the seed often.
 
Do not XOR a value by two differing length values without knowing the implications. It may seem like a good idea but what it actually does is link the fields. While it will give you a longer key value (the {{Wikipedia|Least Common Multiple|w=n}} in length), the fields will be linked such that there are really only as many fields as the {{Wikipedia|Greatest Common Divisor|w=n}}. The number of unique fields determines the theoretical maximum number of keys an attacker has to try.
 
Unique_Key_Fields = Greatest_Common_Divisor(lengths_of_keys) * number_of_keys
 
====Attack Vectors====
First thing you need to know is that XOR is limited poly-alphabetic cipher. The attack vectors that work for poly-alphabetic ciphers work for XOR.
* '''Probability''': In English, letters have different probabilities of occurring because of grammar and spelling rules. XOR does not hide the letter probabilities. This attack only works when the keys are many times smaller than the message.
* '''UTF-8 Rules''': When you convert a string to Base64, UTF-8 encoding is used first. If you assume the inputs are valid UTF-8 encodes some bits can be determined purely upon examination.
* '''Plain Text''': The user captures outputs for known inputs can expose weaknesses in the key.
* '''Brute force''': Attacking the key, secret and/or seed
 
===How to decode with php===
PHP script can be found in [http://lslwiki.net/lslwiki/wakka.php?wakka=llXorBase64StringsCorrect LSL Wiki].
An older version of the code can be found here: [[User:SignpostMarv_Martin/LSL2/llXorBase64StringsCorrect|llXorBase64StringsCorrect in PHP]].
 
Implementation of SignpostMarv's decoder in PHP.
<php>
<?php
/*
* Description: Implementation of SignpostMarv's php base64 decoder.
* Author: Kopilo Hallard
* License: http://creativecommons.org/licenses/by-sa/2.5/
*/
 
/* Cipher (s1 data, s2 key) */
function llXorBase64StringsCorrect($s1, $s2) {
    $s1 = base64_decode($s1); $l1 = strlen($s1);
    $s2 = base64_decode($s2);
    if($l1 > strlen($s2)) $s2 = str_pad($s2, $l1, $s2, STR_PAD_RIGHT);
    return base64_encode($s1 ^ $s2);
}
 
$Skey = "password";
$para1 = $_POST["para1"];
 
$result = llXorBase64StringsCorrect($para1, base64_encode($Skey));
 
echo "Encrypted Data: ".$para1.PHP_EOL;
echo "Unencrypted ".base64_decode($result);
 
?>
</php>
 
Note that until [https://jira.secondlife.com/browse/SCR-35 SCR-35] gets fixed, the function behaves actually like the following PHP code:
 
<php>
<?php
function llXorBase64StringsCorrect($s1, $s2) {
    $s1 = base64_decode($s1); $l1 = strlen($s1);
    $s2 = base64_decode($s2);
    if (($pos = strpos($s2, "\0")) !== false) $s2 = substr($s2, 0, $pos);
    if ($s2 == "") $s2 = "\0";
    if($l1 > strlen($s2)) $s2 = str_pad($s2, $l1, $s2, STR_PAD_RIGHT);
    return base64_encode($s1 ^ $s2);
}
?>
</php>
 
===How to decode with java===
Remember to URLEncode your BASE64 hash if you transfer it vie GET...
 
<java>
      String BASE64datahash = "error";
      String passhash = "error";
 
      try {
        //URLDecode the URL encoded encrypted data
        BASE64datahash = java.net.URLDecoder.decode("KhoFRRYaAUMbEVU%3D", "UTF-8"); //KhoFRRYaAUMbEVU%3D
        System.out.println("BASE64datahash: " + BASE64datahash); //KhoFRRYaAUMbEVU=
 
        //create an array of BASE64 data
        char[] BASE64data = BASE64datahash.toCharArray();
        char[] dataUB = new String(new BASE64Decoder().decodeBuffer(new String(BASE64data))).toCharArray(); //BASE64 decode the data
        System.out.println("encrypted data (but base64 decoded) [dataUB]: " + new String(dataUB));
 
 
        //Encode the secred key/password to BASE64 (Just to show how to use BASE64Encoder)
        //String BASE64password = new String(new BASE64Encoder().encodeBuffer("supersecretpassword".getBytes()));
        //System.out.println("BASE64password: " + new String(BASE64password));
 
        //create array of BASE64 key/password
        //char[] key = BASE64password.toCharArray();
        //char[] keyUB = new String(new BASE64Decoder().decodeBuffer(new String(key))).toCharArray();
        char[] keyUB = "supersecretpassword".toCharArray();
        System.out.println("plaintext key/password [keyUB]: " + new String(keyUB));
 
        //XOR data array chars with corresponding key/password array chars
        int k=0;
        for (int i = 0; i < dataUB.length; i++) {
            dataUB[i] = (char) (dataUB[i] ^ keyUB[k]);
            k++;
 
            //Loop to start of the key if the key is too short
            if (k == keyUB.length)
              k=0;
}
 
        System.out.println("Decoded data [dataUB]: " + new String(dataUB));
       
        } catch (Exception ex) {
            System.out.println("Oops!");
        }
</java>     
<div style="display:none;"><lsl> </lsl></div>
<!--
|cat1=Base64
|cat2=Encoding
|cat3
|cat4 -->
}}
}}

Revision as of 22:29, 24 June 2013

Emblem-important.png Deprecated
(This function has been deprecated, please use llXorBase64 instead.)

Summary

Function: string llXorBase64StringsCorrect( string str1, string str2 );
0.0 Forced Delay
10.0 Energy

Correctly performs an exclusive or on two Base 64 strings.
Returns a string that is a Base64 XOR of str1 and str2.

• string str1 Base64 string
• string str2 Base64 string

str2 repeats if it is shorter than str1. If the inputs are not Base64 strings the result will be erratic.

Caveats

  • This function has been deprecated, please use llXorBase64 instead.
  • During the conversion to a byte array the last (bitcount % 8) are discarded from both str1 and str2. See Implementation for details.
  • Considers any null encountered in str2 to mark the end of str2.

Examples

Deep Notes

Signature

function string llXorBase64StringsCorrect( string str1, string str2 );