Created
March 15, 2014 04:06
-
-
Save cooldaemon/9561700 to your computer and use it in GitHub Desktop.
Python で整数を可逆スクランブルする ref: http://qiita.com/cooldaemon/items/d168b452c976b9dedba6
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
class InverseDoesNotExist(Exception): | |
pass | |
def generate_salt(): | |
""" | |
scramble で使用する salt と inverse_salt を生成する. | |
:return: salt, inverse_salt | |
""" | |
salt = _gen_salt() | |
return salt, _modinv(salt, 0x100000000) | |
def _gen_salt(): | |
salt = random.randint(3, 0xFFFFFFFF) | |
if salt % 2 == 0: | |
salt += 1 | |
return salt | |
def _egcd(a, b): | |
if a == 0: | |
return (b, 0, 1) | |
else: | |
g, y, x = _egcd(b % a, a) | |
return (g, x - (b // a) * y, y) | |
def _modinv(a, m): | |
g, x, y = _egcd(a, m) | |
if g != 1: | |
raise InverseDoesNotExist() | |
else: | |
return x % m |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def scramble(number, salt, inverse_salt): | |
""" | |
数値を相互変換する. | |
:param int number: 変換する整数 | |
:param int salt: 変換のキーとなる整数 | |
:param int inverse_salt: 変換のキーとなる整数の 2^32 を法とする逆数 | |
:return: 変換後の整数 | |
""" | |
_assert_number(number) | |
_assert_salt(salt, inverse_salt) | |
return _trim32bit(_reverse32bit(_trim32bit(number * salt)) * inverse_salt) | |
def _assert_number(number): | |
assert 1 <= number <= 0xFFFFFFFF | |
def _assert_salt(salt, inverse_salt): | |
assert _trim32bit(salt * inverse_salt) == 1 | |
def _reverse32bit(number): | |
number = ((number >> 1) & 0x55555555) | ((number & 0x55555555) << 1) | |
number = ((number >> 2) & 0x33333333) | ((number & 0x33333333) << 2) | |
number = ((number >> 4) & 0x0F0F0F0F) | ((number & 0x0F0F0F0F) << 4) | |
number = ((number >> 8) & 0x00FF00FF) | ((number & 0x00FF00FF) << 8) | |
number = (number >> 16) | (number << 16) | |
return number | |
def _trim32bit(number): | |
return number & 0xFFFFFFFF |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
salt, inverse_salt = generate_salt() | |
def f(number): | |
return scramble(number, salt, inverse_salt) | |
for n in xrange(1, 0xFFFFFFFF): | |
assert f(f(n)) == n |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment