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 encrypted with a passed cipher.
11
 */
12
class AesEncryptingStream 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 $plainText
40
     * @param string $key
41
     * @param CipherMethod $cipherMethod
42
     */
43
    public function __construct(
44
        StreamInterface $plainText,
45
        $key,
46
        CipherMethod $cipherMethod
47
    ) {
48
        $this->stream = $plainText;
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() && $plainTextSize !== null) {
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.
75
            $padding = self::BLOCK_SIZE - $plainTextSize % self::BLOCK_SIZE;
76
            return $plainTextSize + $padding;
77
        }
78
 
79
        return $plainTextSize;
80
    }
81
 
82
    public function isWritable()
83
    {
84
        return false;
85
    }
86
 
87
    public function read($length)
88
    {
89
        if ($length > strlen($this->buffer)) {
90
            $this->buffer .= $this->encryptBlock(
91
                (int)
92
                self::BLOCK_SIZE * ceil(($length - strlen($this->buffer)) / self::BLOCK_SIZE)
93
            );
94
        }
95
 
96
        $data = substr($this->buffer, 0, $length);
97
        $this->buffer = substr($this->buffer, $length);
98
 
99
        return $data ? $data : '';
100
    }
101
 
102
    public function seek($offset, $whence = SEEK_SET)
103
    {
104
        if ($whence === SEEK_CUR) {
105
            $offset = $this->tell() + $offset;
106
            $whence = SEEK_SET;
107
        }
108
 
109
        if ($whence === SEEK_SET) {
110
            $this->buffer = '';
111
            $wholeBlockOffset
112
                = (int) ($offset / self::BLOCK_SIZE) * self::BLOCK_SIZE;
113
            $this->stream->seek($wholeBlockOffset);
114
            $this->cipherMethod->seek($wholeBlockOffset);
115
            $this->read($offset - $wholeBlockOffset);
116
        } else {
117
            throw new LogicException('Unrecognized whence.');
118
        }
119
    }
120
 
121
    private function encryptBlock($length)
122
    {
123
        if ($this->stream->eof()) {
124
            return '';
125
        }
126
 
127
        $plainText = '';
128
        do {
129
            $plainText .= $this->stream->read((int) ($length - strlen($plainText)));
130
        } while (strlen($plainText) < $length && !$this->stream->eof());
131
 
132
        $options = OPENSSL_RAW_DATA;
133
        if (!$this->stream->eof()
134
            || $this->stream->getSize() !== $this->stream->tell()
135
        ) {
136
            $options |= OPENSSL_ZERO_PADDING;
137
        }
138
 
139
        $cipherText = openssl_encrypt(
140
            $plainText,
141
            $this->cipherMethod->getOpenSslName(),
142
            $this->key,
143
            $options,
144
            $this->cipherMethod->getCurrentIv()
145
        );
146
 
147
        $this->cipherMethod->update($cipherText);
148
 
149
        return $cipherText;
150
    }
151
}