Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Crypt
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 3
56
0.00% covered (danger)
0.00%
0 / 1
 encrypt
n/a
0 / 0
n/a
0 / 0
0
 decrypt
n/a
0 / 0
n/a
0 / 0
0
 cleanup
n/a
0 / 0
n/a
0 / 0
0
 canDecrypt
n/a
0 / 0
n/a
0 / 0
0
 getCryptTypes
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 factory
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 getCreateDescriptors
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 getTallyDescriptors
n/a
0 / 0
n/a
0 / 0
0
 updateTallyContext
n/a
0 / 0
n/a
0 / 0
0
 updateDbForTallyJob
n/a
0 / 0
n/a
0 / 0
0
 cleanupDbForTallyJob
n/a
0 / 0
n/a
0 / 0
0
1<?php
2
3namespace MediaWiki\Extension\SecurePoll\Crypt;
4
5use InvalidArgumentException;
6use MediaWiki\Extension\SecurePoll\Context;
7use MediaWiki\Extension\SecurePoll\Entities\Election;
8use MediaWiki\Shell\Shell;
9use MediaWiki\Status\Status;
10use Wikimedia\Rdbms\IDatabase;
11
12/**
13 * Cryptography module
14 */
15abstract class Crypt {
16    /**
17     * Encrypt some data. When successful, the value member of the Status object
18     * will contain the encrypted record.
19     * @param string $record
20     * @return Status
21     */
22    abstract public function encrypt( $record );
23
24    /**
25     * Decrypt some data. When successful, the value member of the Status object
26     * will contain the encrypted record.
27     * @param string $record
28     * @return Status
29     */
30    abstract public function decrypt( $record );
31
32    /**
33     * @internal Generic clean up function. Internal functions can call this to clean up
34     * after themselves or callers can manually clean up after processing.
35     * Ideally, functions would be self-contained but due to performance
36     * constraints, this is not always possible. In those cases, the caller
37     * should be responsible for cleanup.
38     */
39    abstract public function cleanup();
40
41    /**
42     * Returns true if the object can decrypt data, false otherwise.
43     */
44    abstract public function canDecrypt();
45
46    /**
47     * Returns a list of supported Crypt subclasses for encrypting votes.
48     *
49     * @return array<string,class-string<Crypt>|false>
50     */
51    public static function getCryptTypes() {
52        $cryptTypes = [
53            'none' => false
54        ];
55
56        if ( !Shell::isDisabled() ) {
57            $cryptTypes['gpg'] = GpgCrypt::class;
58        }
59
60        if ( extension_loaded( 'openssl' ) ) {
61            $cryptTypes['openssl'] = OpenSslCrypt::class;
62        }
63
64        return $cryptTypes;
65    }
66
67    /**
68     * Create an encryption object of the given type.
69     * @param Context $context
70     * @param string $type
71     * @param Election $election
72     * @return self|false False when encryption type is set to "none"
73     */
74    public static function factory( $context, $type, $election ) {
75        $cryptTypes = self::getCryptTypes();
76
77        if ( !isset( $cryptTypes[$type] ) ) {
78            throw new InvalidArgumentException( "Invalid crypt type: $type" );
79        }
80        $class = $cryptTypes[$type];
81
82        return $class ? new $class( $context, $election ) : false;
83    }
84
85    /**
86     * Return descriptors for any properties this type requires for poll
87     * creation, for the election, questions, and options.
88     *
89     * The returned array should have three keys, "election", "question", and
90     * "option", each mapping to an array of HTMLForm descriptors.
91     *
92     * The descriptors should have an additional key, "SecurePoll_type", with
93     * the value being "property" or "message".
94     *
95     * @return array
96     */
97    public static function getCreateDescriptors() {
98        return [
99            'election' => [],
100            'question' => [],
101            'option' => [],
102        ];
103    }
104
105    /**
106     * Return descriptors for any properties this type requires for poll
107     * tallying.
108     *
109     * @return array
110     */
111    abstract public function getTallyDescriptors(): array;
112
113    /**
114     * Update the given context with any information needed for tallying.
115     *
116     * This allows some information, e.g. private keys, to be used for a
117     * single request and not added to the database.
118     *
119     * @param Context $context
120     * @param array $data
121     */
122    abstract public function updateTallyContext( Context $context, array $data ): void;
123
124    /**
125     * Update the database with any information needed for tallying via a job.
126     *
127     * This may include adding private keys to the database. While not ideal,
128     * this is nothing new in SecurePoll. It should only be done once an
129     * election is finished, and should be cleaned up.
130     *
131     * @see Crypt::cleanupDbForTallyJob
132     * @param int $electionId
133     * @param IDatabase $dbw
134     * @param array $data
135     */
136    abstract public function updateDbForTallyJob(
137        int $electionId,
138        IDatabase $dbw,
139        array $data
140    ): void;
141
142    /**
143     * Clean up the database after tallying via a job.
144     *
145     * @see Crypt::updateDbForTallyJob
146     * @param int $electionId
147     * @param IDatabase $dbw
148     */
149    abstract public function cleanupDbForTallyJob( int $electionId, IDatabase $dbw ): void;
150}