Why it doesn't work?

作業のメモ、記録をブログに残しています。

Python アルファベットと数字をn文字ずらした文字列を得る(シーザー暗号)

会社のPCはパスワードを毎月変更しないといけません。規則が厳しすぎて、毎月アルファベットと数字を一文字ずらした文字列を新しいパスワードと使用しています。
というわけで、pythonでパスワード生成コードを実装してみます。
まず、シーザー暗号についてですが、詳しくはWikiを一読下さい。
シーザー暗号 - Wikipedia

Pythonには標準モジュールのcodecsにROT13が実装されているので、ROT13自体の実装は簡単です。

>>> import codecs
>>> codecs.decode("Hello", "rot13")
u'Uryyb'

ただ、ROT13はアルファベットを13文字ずらすので、2回実行すると元の文字列にたどりついてしまいます。また、数字は対象外です。

>>> codecs.decode("Uryyb", "rot13")
u'Hello'
>>> codecs.decode("Hello1", "rot13")
u'Uryyb1'

できれば、一つの文字列をベースに26ヶ月は使い回したい。数字も対象にしたい。ということで以下のような実装にしてみました。

#!/usr/bin/env python
def caesar(s, n):
    ns = []
    for ch in s:
        # A - Z
        if ('A' <= ch and ch <= 'Z'):
            ns.append(chr((ord(ch) - ord('A') - n) % 26 + ord('A')))
        # a - z
        elif ('a' <= ch and ch <= 'z'):
            ns.append(chr((ord(ch) - ord('a') - n) % 26 + ord('a')))
        # 0 - 9
        elif ('0' <= ch and ch <= '9'):
            ns.append(chr((ord(ch) - ord('0') - n) % 10 + ord('0')))
        # no change for other characters
        else:
            ns.append(ch)
    return "".join(ns)

result = caesar("Hello#0", 1)
print(result)

これを実行すると、以下のような結果が出力されます。あってます。たぶん。。。

Gdkkn#9

シフト数を変更する場合には、caesar()の第二引数を変更して下さい。シフトする方向を変更する場合には、"- n" を"+ n"にすればOKのはず。未確認!
今日はここまで!