Browse Source

Write session data to single key

This prevents decrypting values multiple times.
tags/v8.2beta1
Lukas Reschke 8 years ago
parent
commit
e579dd62fd
2 changed files with 34 additions and 20 deletions
  1. 30
    16
      lib/private/session/cryptosessiondata.php
  2. 4
    4
      tests/lib/session/cryptowrappingtest.php

+ 30
- 16
lib/private/session/cryptosessiondata.php View File

class CryptoSessionData implements \ArrayAccess, ISession { class CryptoSessionData implements \ArrayAccess, ISession {
/** @var ISession */ /** @var ISession */
protected $session; protected $session;

/** @var \OCP\Security\ICrypto */ /** @var \OCP\Security\ICrypto */
protected $crypto; protected $crypto;

/** @var string */ /** @var string */
protected $passphrase; protected $passphrase;
/** @var array */
protected $sessionValues;
CONST encryptedSessionName = 'encrypted_session_data';


/** /**
* @param ISession $session * @param ISession $session
* @param ICrypto $crypto * @param ICrypto $crypto
* @param string $passphrase * @param string $passphrase
*/ */
public function __construct(ISession $session, ICrypto $crypto, $passphrase) {
public function __construct(ISession $session,
ICrypto $crypto,
$passphrase) {
$this->crypto = $crypto; $this->crypto = $crypto;
$this->session = $session; $this->session = $session;
$this->passphrase = $passphrase; $this->passphrase = $passphrase;
$this->initializeSession();
}

protected function initializeSession() {
$encryptedSessionData = $this->session->get(self::encryptedSessionName);
try {
$this->sessionValues = json_decode(
$this->crypto->decrypt($encryptedSessionData, $this->passphrase),
true
);
} catch (\Exception $e) {
$this->sessionValues = [];
}
} }


/** /**
* @param mixed $value * @param mixed $value
*/ */
public function set($key, $value) { public function set($key, $value) {
$encryptedValue = $this->crypto->encrypt(json_encode($value), $this->passphrase);
$this->session->set($key, $encryptedValue);
$this->sessionValues[$key] = $value;
$encryptedValue = $this->crypto->encrypt(json_encode($this->sessionValues), $this->passphrase);
$this->session->set(self::encryptedSessionName, $encryptedValue);
} }


/** /**
* @return string|null Either the value or null * @return string|null Either the value or null
*/ */
public function get($key) { public function get($key) {
$encryptedValue = $this->session->get($key);
if ($encryptedValue === null) {
return null;
}


try {
$value = $this->crypto->decrypt($encryptedValue, $this->passphrase);
return json_decode($value);
} catch (\Exception $e) {
return null;
if(isset($this->sessionValues[$key])) {
return $this->sessionValues[$key];
} }

return null;
} }


/** /**
* @return bool * @return bool
*/ */
public function exists($key) { public function exists($key) {
return $this->session->exists($key);
return isset($this->sessionValues[$key]);
} }


/** /**
* @param string $key * @param string $key
*/ */
public function remove($key) { public function remove($key) {
$this->session->remove($key);
unset($this->sessionValues[$key]);
$this->session->remove(self::encryptedSessionName);
} }


/** /**
* Reset and recreate the session * Reset and recreate the session
*/ */
public function clear() { public function clear() {
$this->sessionValues = [];
$this->session->clear(); $this->session->clear();
} }



+ 4
- 4
tests/lib/session/cryptowrappingtest.php View File



$this->wrappedSession->expects($this->once()) $this->wrappedSession->expects($this->once())
->method('set') ->method('set')
->with('key', $this->crypto->encrypt(json_encode($unencryptedValue)));
$this->instance->set('key', $unencryptedValue);
->with('encrypted_session_data', $this->crypto->encrypt(json_encode(['encrypted_session_data' => $unencryptedValue])));
$this->instance->set('encrypted_session_data', $unencryptedValue);
} }


public function testUnwrappingGet() { public function testUnwrappingGet() {


$this->wrappedSession->expects($this->once()) $this->wrappedSession->expects($this->once())
->method('get') ->method('get')
->with('key')
->with('encrypted_session_data')
->willReturnCallback(function () use ($encryptedValue) { ->willReturnCallback(function () use ($encryptedValue) {
return $encryptedValue; return $encryptedValue;
}); });


$this->assertSame($unencryptedValue, $this->wrappedSession->get('key'));
$this->assertSame($unencryptedValue, $this->wrappedSession->get('encrypted_session_data'));
} }
} }

Loading…
Cancel
Save