You are right, it is an accident that unicode can be encoded to base64. It just annoys me that the Python 2.6 error for this is &quot;TypeError: character mapping must return integer, None or unicode&quot;.<br><br>In that case, how would you feel about updating PlainTextPasswordManager instead? It is not like the others because it won&#39;t work unless hash is a unicode<br>
<br>PlainTextPasswordManager().encodePassword(u&quot;password&quot;) =&gt; unicode<br>PlainTextPasswordManager().checkPassword(unicode, unicode)<br><br>and the others break unless hash is always a str.<br><br>.encodePassword(u&quot;password&quot;) =&gt; str<br>
.checkPassword(str, unicode)<br><br><br>Here&#39;s my DelegatingPasswordManager. I might update it so .encodePassword() uses the unnamed IPasswordManager if installed. It would be nice if IPasswordManager included the name of the scheme to go between {} before the hash proper.<br>
<br><span style="font-family: courier new,monospace;">class DelegatingPasswordManager(object):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    &quot;&quot;&quot;Check passwords stored RFC 2307 style as {scheme}hash.</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    Delegates to named IPasswordManager utilities.&quot;&quot;&quot;</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    implements(IPasswordManager)</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    SCHEME = u&quot;Delegating Password Manager&quot;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    _scheme = re.compile(r&quot;^{(?P&lt;scheme&gt;[^}]*)}(?P&lt;hash&gt;.*)$&quot;)</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    def encodePassword(self, password):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        raise NotImplementedError(&quot;DelegatingPasswordManager can only check passwords&quot;)</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    def checkPassword(self, encoded_password, password):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        handler = None</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        match = self._scheme.match(encoded_password)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        if not match:</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">            raise ValueError(&quot;Encoded password must be formatted as {scheme}hash.&quot;)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        try:</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">            scheme = match.group(&quot;scheme&quot;)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">            handler = getUtility(IPasswordManager, scheme)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        except zope.component.interfaces.ComponentLookupError, e:</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">            raise LookupError(&quot;Handler for password encryption scheme {%s} not found.&quot; % scheme, e)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        if handler != self:</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">            return handler.checkPassword(encoded_password, password)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        return False</span><br><br>