PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / 261011
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions v261011
261011 261001 260927 260917 260913 260909 260829 260814 260805 110710 110731 110812 110815 110912 110913 110915 110926 110927 111002 111003 111011 111017 111029 111105 111206 All 192 releases
← All changes | src/includes/classes/utils-defuse.inc.php +58 -24 260927 → 261011 View file →
@@ -73,8 +73,31 @@
73 73 return array(self::secret_key_hash($secret_key) => $defuse_key);
74 74 }
75 75
76 76 /**
77 + * Checks whether a stored Defuse key can be loaded.
78 + *
79 + * @since 261006
80 + *
81 + * @param string $defuse_key Stored ASCII-safe Defuse key.
82 + * @return bool True for a valid key, else false.
83 + */
84 + private static function valid_defuse_key($defuse_key)
85 + {
86 + if (!is_string($defuse_key) || !isset($defuse_key[0])) {
87 + return false;
88 + }
89 + try {
90 + Key::loadFromAsciiSafeString($defuse_key);
91 + return true;
92 + } catch (Throwable $Exception) {
93 + return false;
94 + } catch (Exception $Exception) {
95 + return false;
96 + }
97 + }
98 +
99 + /**
77 100 * Migrates legacy Defuse key mappings to hashed mappings.
78 101 *
79 102 * Preserves the existing Defuse keys while creating hashed mappings for
80 103 * the current default key, recovery history, and custom secret keys.
@@ -87,20 +110,33 @@
87 110 public static function migrate_legacy_defuse_key_mappings()
88 111 {
89 112 $options = array();
90 113
91 - // Migrate the current default mapping without changing its Defuse key.
114 + //261006.0424 Fingerprinted associations are authoritative; legacy data fills only missing or invalid keys, including direct upgrades.
92 115 $legacy_mapping = $GLOBALS['WS_PLUGIN__']['s2member']['o']['def_combo_encryption_key'];
93 116 $converted_defuse_keys = self::convert_legacy_defuse_key_mapping($legacy_mapping);
94 - $defuse_keys = $converted_defuse_keys ? $converted_defuse_keys : $GLOBALS['WS_PLUGIN__']['s2member']['o']['secret_key_to_defuse_key'];
95 - if ($converted_defuse_keys && $converted_defuse_keys !== $GLOBALS['WS_PLUGIN__']['s2member']['o']['secret_key_to_defuse_key']) {
117 + $defuse_keys = $GLOBALS['WS_PLUGIN__']['s2member']['o']['secret_key_to_defuse_key'];
118 + foreach ($converted_defuse_keys as $_secret_key_hash => $_defuse_key) {
119 + if (!isset($defuse_keys[$_secret_key_hash]) || !self::valid_defuse_key($defuse_keys[$_secret_key_hash])) {
120 + $defuse_keys[$_secret_key_hash] = $_defuse_key;
121 + }
122 + }
123 + if ($defuse_keys !== $GLOBALS['WS_PLUGIN__']['s2member']['o']['secret_key_to_defuse_key']) {
96 124 $defuse_keys_update = $defuse_keys;
97 125 array_unshift($defuse_keys_update, 'update-signal');
98 126 $options['ws_plugin__s2member_secret_key_to_defuse_key'] = $defuse_keys_update;
99 127 }
100 128
101 - // Preserve default mappings as recovery-only history; normal decryption does not search it.
129 + //261006.0424 Keep canonical recovery history ahead of legacy additions; conflicting keys remain available for explicit recovery, not normal lookup.
102 130 $defuse_key_history = $defuse_keys ? array($defuse_keys) : array();
131 + foreach ($GLOBALS['WS_PLUGIN__']['s2member']['o']['secret_key_to_defuse_key_history'] as $_defuse_keys) {
132 + if (is_array($_defuse_keys) && count($_defuse_keys) === 1 && !in_array($_defuse_keys, $defuse_key_history, true)) {
133 + $defuse_key_history[] = $_defuse_keys;
134 + }
135 + }
136 + if ($converted_defuse_keys && !in_array($converted_defuse_keys, $defuse_key_history, true)) {
137 + $defuse_key_history[] = $converted_defuse_keys;
138 + }
103 139 foreach ($GLOBALS['WS_PLUGIN__']['s2member']['o']['def_combo_encryption_key_history'] as $_legacy_mapping) {
104 140 $_defuse_keys = self::convert_legacy_defuse_key_mapping($_legacy_mapping);
105 141 if ($_defuse_keys && !in_array($_defuse_keys, $defuse_key_history, true)) {
106 142 $defuse_key_history[] = $_defuse_keys;
@@ -105,13 +141,8 @@
105 141 if ($_defuse_keys && !in_array($_defuse_keys, $defuse_key_history, true)) {
106 142 $defuse_key_history[] = $_defuse_keys;
107 143 }
108 144 }
109 - foreach ($GLOBALS['WS_PLUGIN__']['s2member']['o']['secret_key_to_defuse_key_history'] as $_defuse_keys) {
110 - if (is_array($_defuse_keys) && count($_defuse_keys) === 1 && !in_array($_defuse_keys, $defuse_key_history, true)) {
111 - $defuse_key_history[] = $_defuse_keys;
112 - }
113 - }
114 145 $defuse_key_history = array_slice($defuse_key_history, 0, 10);
115 146 if ($defuse_key_history !== $GLOBALS['WS_PLUGIN__']['s2member']['o']['secret_key_to_defuse_key_history']) {
116 147 $defuse_key_history_update = $defuse_key_history;
117 148 array_unshift($defuse_key_history_update, 'update-signal');
@@ -123,10 +154,13 @@
123 154 foreach ($GLOBALS['WS_PLUGIN__']['s2member']['o']['def_custom_combo_encryption_keys'] as $_secret_key => $_defuse_key) {
124 155 $_secret_key = (string) $_secret_key;
125 156 $_defuse_key = (string) $_defuse_key;
126 157
127 - if (isset($_secret_key[0]) && isset($_defuse_key[0])) {
128 - $custom_defuse_keys[self::secret_key_hash($_secret_key)] = $_defuse_key;
158 + if (isset($_secret_key[0]) && self::valid_defuse_key($_defuse_key)) {
159 + $_secret_key_hash = self::secret_key_hash($_secret_key);
160 + if (!isset($custom_defuse_keys[$_secret_key_hash]) || !self::valid_defuse_key($custom_defuse_keys[$_secret_key_hash])) {
161 + $custom_defuse_keys[$_secret_key_hash] = $_defuse_key;
162 + }
129 163 }
130 164 }
131 165 if ($custom_defuse_keys !== $GLOBALS['WS_PLUGIN__']['s2member']['o']['custom_secret_key_to_defuse_key']) {
132 166 array_unshift($custom_defuse_keys, 'update-signal');
@@ -156,29 +190,29 @@
156 190 $secret_key = c_ws_plugin__s2member_utils_encryption::key($secret_key);
157 191 $secret_key_hash = self::secret_key_hash($secret_key);
158 192
159 193 if ($has_custom_secret_key) {
160 - // Prefer the legacy custom mapping during the compatibility release.
194 + //261006.0424 Prefer valid fingerprinted keys while retaining legacy lookup for installations not yet migrated.
195 + $custom_defuse_keys = $GLOBALS['WS_PLUGIN__']['s2member']['o']['custom_secret_key_to_defuse_key'];
196 + if ($secret_key_hash && isset($custom_defuse_keys[$secret_key_hash]) && self::valid_defuse_key($custom_defuse_keys[$secret_key_hash])) {
197 + return $custom_defuse_keys[$secret_key_hash];
198 + }
161 199 $legacy_custom_defuse_keys = $GLOBALS['WS_PLUGIN__']['s2member']['o']['def_custom_combo_encryption_keys'];
162 - if ($secret_key && !empty($legacy_custom_defuse_keys[$secret_key])) {
200 + if ($secret_key && isset($legacy_custom_defuse_keys[$secret_key]) && self::valid_defuse_key($legacy_custom_defuse_keys[$secret_key])) {
163 201 return $legacy_custom_defuse_keys[$secret_key];
164 202 }
165 - // Fall back to the hashed custom mapping prepared for later releases.
166 - $custom_defuse_keys = $GLOBALS['WS_PLUGIN__']['s2member']['o']['custom_secret_key_to_defuse_key'];
167 - if ($secret_key_hash && !empty($custom_defuse_keys[$secret_key_hash])) {
168 - return $custom_defuse_keys[$secret_key_hash];
169 - }
170 203 return '';
171 204 }
172 - // Prefer the legacy default mapping during the compatibility release.
205 + $defuse_keys = $GLOBALS['WS_PLUGIN__']['s2member']['o']['secret_key_to_defuse_key'];
206 + if ($secret_key_hash && isset($defuse_keys[$secret_key_hash]) && self::valid_defuse_key($defuse_keys[$secret_key_hash])) {
207 + return $defuse_keys[$secret_key_hash];
208 + }
173 209 $legacy_mapping = $GLOBALS['WS_PLUGIN__']['s2member']['o']['def_combo_encryption_key'];
174 210 if ($secret_key && $legacy_mapping && strpos($legacy_mapping, $secret_key."\n") === 0) {
175 - return substr($legacy_mapping, strlen($secret_key) + 1);
211 + $legacy_defuse_key = substr($legacy_mapping, strlen($secret_key) + 1);
212 + return self::valid_defuse_key($legacy_defuse_key) ? $legacy_defuse_key : '';
176 213 }
177 - // Fall back to the hashed default mapping prepared for later releases.
178 - $defuse_keys = $GLOBALS['WS_PLUGIN__']['s2member']['o']['secret_key_to_defuse_key'];
179 -
180 - return ($secret_key_hash && !empty($defuse_keys[$secret_key_hash])) ? $defuse_keys[$secret_key_hash] : '';
214 + return '';
181 215 }
182 216
183 217 /**
184 218 * Creates and stores a new Defuse encryption key.