Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
namespace Aws\Crypto;
3
 
4
use GuzzleHttp\Psr7\StreamDecoratorTrait;
5
use \LogicException;
6
use Psr\Http\Message\StreamInterface;
7
use Aws\Crypto\Cipher\CipherMethod;
8
 
9
/**
10
 * @internal Represents a stream of data to be decrypted with passed cipher.
11
 */
12
class AesDecryptingStream implements AesStreamInterface
13
{
14
    const BLOCK_SIZE = 16; // 128 bits
15
 
16
    use StreamDecoratorTrait;
17
 
18
    /**
19
     * @var string
20
     */
21
    private $buffer = '';
22
 
23
    /**
24
     * @var CipherMethod
25
     */
26
    private $cipherMethod;
27
 
28
    /**
29
     * @var string
30
     */
31
    private $key;
32
 
33
    /**
34
     * @var StreamInterface
35
     */
36
    private $stream;
37
 
38
    /**
39
     * @param StreamInterface $cipherText
40
     * @param string $key
41
     * @param CipherMethod $cipherMethod
42
     */
43
    public function __construct(
44
        StreamInterface $cipherText,
45
        $key,
46
        CipherMethod $cipherMethod
47
    ) {
48
        $this->stream = $cipherText;
49
        $this->key = $key;
50
        $this->cipherMethod = clone $cipherMethod;
51
    }
52
 
53
    public function getOpenSslName()
54
    {
55
        return $this->cipherMethod->getOpenSslName();
56
    }
57
 
58
    public function getAesName()
59
    {
60
        return $this->cipherMethod->getAesName();
61
    }
62
 
63
    public function getCurrentIv()
64
    {
65
        return $this->cipherMethod->getCurrentIv();
66
    }
67
 
68
    public function getSize()
69
    {
70
        $plainTextSize = $this->stream->getSize();
71
 
72
        if ($this->cipherMethod->requiresPadding()) {
73
            // PKCS7 padding requires that between 1 and self::BLOCK_SIZE be
74
            // added to the plaintext to make it an even number of blocks. The
75
            // plaintext is between strlen($cipherText) - self::BLOCK_SIZE and
76
            // strlen($cipherText) - 1
77
            return null;
78
        }
79
 
80
        return $plainTextSize;
81
    }
82
 
83
    public function isWritable()
84
    {
85
        return false;
86
    }
87
 
88
    public function read($length)
89
    {
90
        if ($length > strlen($this->buffer)) {
91
            $this->buffer .= $this->decryptBlock(
92
                (int) (
93
                        self::BLOCK_SIZE * ceil(($length - strlen($this->buffer)) / self::BLOCK_SIZE)
94
                )
95
            );
96
        }
97
 
98
        $data = substr($this->buffer, 0, $length);
99
        $this->buffer = substr($this->buffer, $length);
100
 
101
        return $data ? $data : '';
102
    }
103
 
104
    public function seek($offset, $whence = SEEK_SET)
105
    {
106
        if ($offset === 0 && $whence === SEEK_SET) {
107
            $this->buffer = '';
108
            $this->cipherMethod->seek(0, SEEK_SET);
109
            $this->stream->seek(0, SEEK_SET);
110
        } else {
111
            throw new LogicException('AES encryption streams only support being'
112
                . ' rewound, not arbitrary seeking.');
113
        }
114
    }
115
 
116
    private function decryptBlock($length)
117
    {
118
        if ($this->stream->eof()) {
119
            return '';
120
        }
121
 
122
        $cipherText = '';
123
        do {
124
            $cipherText .= $this->stream->read((int) ($length - strlen($cipherText)));
125
        } while (strlen($cipherText) < $length && !$this->stream->eof());
126
 
127
        $options = OPENSSL_RAW_DATA;
128
        if (!$this->stream->eof()
129
            && $this->stream->getSize() !== $this->stream->tell()
130
        ) {
131
            $options |= OPENSSL_ZERO_PADDING;
132
        }
133
 
134
        $plaintext = openssl_decrypt(
135
            $cipherText,
136
            $this->cipherMethod->getOpenSslName(),
137
            $this->key,
138
            $options,
139
            $this->cipherMethod->getCurrentIv()
140
        );
141
 
142
        $this->cipherMethod->update($cipherText);
143
 
144
        return $plaintext;
145
    }
146
}