2

I am trying to work with an api for which there is minimal documentation. The only hint I have is an example of "pseudo-code" of php. I dont know php, and can't seem to figure out what they mean here.

$codice_sha1 = sha1(implode(‘,’, $params) . ‘,’ . $secret);
$codice = base64_encode($key . ‘:’ . $codice_sha1);

impode seems to be a thing like JavaScript's join but usually params are key value pairs. So I really don't see how this is supposed to work. Any php ninja's out there with knowledge of the idioms know what this means?

Here is the full api documentation https://www.docebo.com/lms-docebo-api-third-party-integration/#onlinedoc

The question is not "what is implode" but "what does it usually mean in this context"

Fresheyeball
  • 29,567
  • 20
  • 102
  • 164
  • http://php.net/manual/en/function.implode.php – Dan Dec 16 '15 at 23:03
  • I looked it up, and even played with it in a test environment, It doesn't make sense to me how its supposed to encode parameters. – Fresheyeball Dec 16 '15 at 23:03
  • 4
    sidenote: these curly quotes `‘ ’` if part of your real code, will break that code. – Funk Forty Niner Dec 16 '15 at 23:03
  • If you have an array with "1" and "2" in there implode on that array will give you a string "1, 2" ... it doesn't "encode" anything. – developerwjk Dec 16 '15 at 23:04
  • @Fred-ii- that was a copy paste from their docs :( – Fresheyeball Dec 16 '15 at 23:04
  • ah, I had a feeling it would be. – Funk Forty Niner Dec 16 '15 at 23:05
  • @Rizier123 yes, I know. But I don't understand how its supposed to work in this context. Params are usually key value pairs where I come from. Is it supposed to discard the keys? Is that normal for php? – Fresheyeball Dec 16 '15 at 23:05
  • 2
    Yes it discards the keys. The point is to end up with a string representation of a list of values. – developerwjk Dec 16 '15 at 23:06
  • Is there a normal way that people encode `$params` in php? As a flat array or an "associative array" ? – Fresheyeball Dec 16 '15 at 23:08
  • As to is this normal in PHP, is it normal to do sha1 on a string list of the parameters and then base64 encode that? What's the point? Doesn't seem "normal" to anything. – developerwjk Dec 16 '15 at 23:09
  • @developerwjk I had a feeling :( Its so weird. – Fresheyeball Dec 16 '15 at 23:09
  • But these parameters are being prepared to be sent to a web api right...and a web api can only receive the parameters as a string or strings...so here rather than each being encrypted separate they're being put together as one string and encrypted then sent to the web api...actually makes sense now. – developerwjk Dec 16 '15 at 23:11
  • In other words, these aren't parameters coming in, but going out, so yeah, makes sense. – developerwjk Dec 16 '15 at 23:11
  • @developerwjk ok good!!!! because I really don't get it. Can you make an explanation of what is intended here in an answer? – Fresheyeball Dec 16 '15 at 23:12
  • SHA1 is a hash which can't really be decoded or decrypted. Its more likely that its a hash of a password and will be saved in the database and will be used to authenticate a user at some point in the future. Also, the `$secret` variable hints to this. – br3nt Dec 16 '15 at 23:29
  • Also, there are many ways to encode and decode an array or associative array. I like to use the JSON library: `$json = json_encode($my_associative_array)` and `$my_associative_array = json_decode($json)`. – br3nt Dec 16 '15 at 23:30

3 Answers3

1

In the code example you have given, the purpose of implode(',', $params) . ',' . $secret is to concatenate all the individual bits of information into a single String.

To break it down into individual lines of code, you can see relatively clearly what's going on.

// some example values to be encoded
$secret = 'xxxyyy';
$key = 'some key';
$params = array('a', 'b', 'b');

// concatenate the values into a single string ready for encoding
$imploded = implode(',', $params); // becomes string 'a,b,c'
$concatenated_str = 'a,b,c' . ',' . $secret; // becomes 'a,b,c,xxxyyy'

// encode the string
$codice_sha1 = sha1($concatenated_str); // creates a SHA1 hash of the string
$codice = base64_encode("{$key}:{$codice_sha1}"); // creates base64 encoding of the SHA1 hash

The purpose of the code is then to encode a string (perhaps a password hash for later authentication)

br3nt
  • 9,017
  • 3
  • 42
  • 63
  • So this is helpful. But the api has parameters as named fields. How would you encode something like `{ someParam : "foo"}` in an array that works with implode? – Fresheyeball Dec 16 '15 at 23:17
  • You could encode may different ways. You could use a foreach loop concatenating the keys and values together, or the JSON library. So long as the end result is single String. – br3nt Dec 16 '15 at 23:21
  • You cannot, so that is not what is happening in the API link you provided. `implode(['key1' => 'val1', 'key2' => 'val2']);` produces exactly the same output as `implode(['val1', 'val2']);` – alzee Dec 16 '15 at 23:22
1

Basically how I am looking at this is as follows. On the web you have two ways to send parameters to another site: GET and POST. Either way the parameters will be strings, not arrays or any datatype. That's just how HTTP works.

Ok. So I'm writing an api. I want the parameters coming in sha1 e̶n̶c̶r̶y̶p̶t̶e̶d̶ hashed. How shall I do this? I can tell my customers to send it like:

$requestUrl = "example.com/api?key1=" . sha1($value1) . "&key2=" . sha1($value2); 

OR

$params = array("key1" => "value1", "key2" => "value2");
$requestUrl = "example.com/api?params=" .  base64_encode(sha1(implode(',', $params)));

If there is a long list of params, the second one makes more sense.

Also, if you don't want meddlers to try and decrypt each param separately which would be much easier to figure out I think than decrypting them all together, you might opt for this approach.

Base64 encoding gets around having to worry about characters like & which can break a querystring on a GET request.

Basically, its dictated by the API creator. Its not the choice of the developer who is using the API.

EDIT: My initial thought made more sense when I forgot that sha1() is only a hashing algorithm and not reversible encryption. There might be a way they could still make this work, but its convoluted and a very bad idea.

developerwjk
  • 8,619
  • 2
  • 17
  • 33
  • But implode tosses away the keys. So how can the api read named parameters? – Fresheyeball Dec 16 '15 at 23:19
  • @Fresheyeball I would imagine they expect them in a certain order. I should also add to this that the base 64 encoding is to prevent having to worry about characters like `&` that would cause a problem for GET. – developerwjk Dec 16 '15 at 23:20
  • oh hell, so I guess I will assume the parameters go in the same order they are presented in the documentation :( – Fresheyeball Dec 16 '15 at 23:21
  • SHA1 is a hash though.... you can't really decode or decrypt it. For this reason I don't think it would be used to transport data in a request. I could be wrong though... – br3nt Dec 16 '15 at 23:24
  • @br3nt Yeah, I was just thinking that actually. – developerwjk Dec 16 '15 at 23:29
  • @br3nt unless the params are just selections from a pre-existing list, and the value for `$secret` is something dictated to you by the API guys. – developerwjk Dec 16 '15 at 23:31
  • @developerwjk, how do you mean? In what manner would the encoded string be decoded to become usable again? – br3nt Dec 16 '15 at 23:34
  • @br3nt Well, sha1 is hackable by brute force. If the params are always from a finite list of values, they could keep a database of the hashes for the different combinations. But obviously its not a good design. – developerwjk Dec 16 '15 at 23:41
  • @developerwjk, not a good design lol, but I do like the idea of sending request params base64 encoded or even encrypted in some fashion. – br3nt Dec 16 '15 at 23:46
0

Implode in php simply takes an array and turns it into a string by concatenating all of the array elements, separated by the delimiter specified.

So implode('|', [1,2,3,4,5]); results in the string "1|2|3|4|5".

It is not generally used on hashes as the keys are lost, and does not work at all on a multidimensional array. I don't understand how you came to the conclusion that $params is anything but a normal, one-dimensional array.

alzee
  • 1,393
  • 1
  • 10
  • 21
  • Is there a normal way that people encode `$params` into a flat array in php? I've always used a map of some kind. – Fresheyeball Dec 16 '15 at 23:07
  • Do you mean "one dimensional" by flat? If it's being used with `implode()`, then it already is flat. It seems that you're assuming `$params` is multidimensional, but in this context, it simply can't be. – alzee Dec 16 '15 at 23:09
  • What do you mean by flat array. Maybe what [array_values](http://php.net/manual/en/function.array-values.php) does – Dan Dec 16 '15 at 23:09
  • by flat array, I mean one dimensional. And I tested implode on a couple arrays, and it does work on associative arrays. – Fresheyeball Dec 16 '15 at 23:10
  • @Fresheyeball Do you mean as in http://stackoverflow.com/questions/1319903/how-to-flatten-a-multidimensional-array – k0pernikus Dec 16 '15 at 23:10
  • I'm not sure I'd call throwing away the keys "working" but yes, that is how it behaves. On multidimensional arrays it is useless. – alzee Dec 16 '15 at 23:12
  • If you want to keep the keys, use `json_encode` or `serialize` - also works for multi-dimensional arrays – Justin E Dec 16 '15 at 23:15
  • There are many ways to preserve the keys, but using any of them except `implode()` is going to generate the wrong output in this case, since the `sha1` hash of the result will be different. – alzee Dec 16 '15 at 23:18