python的traceback模块

最近被try不try的搅和的头疼,很二货的各种不好定位bug。
后来想起来了还有个很好用的模块一直被我遗忘了。
那就是 巴拉巴拉~~traceback模块。
本来打算自己写上一发的,但是度娘出一篇相当感人至深的traceback的文字,就直接贴上吧。

以下文字100%摘抄!!!

源文章:搞清楚 Python traceback
作者:SamChi
发表于2013-12-01 15:43

1.Python中的异常栈跟踪
之前在做Java的时候,异常对象默认就包含stacktrace相关的信息,通过异常对象的相关方法printStackTrace()和getStackTrace()等方法就可以取到异常栈信息,能打印到log辅助调试或者做一些别的事情。但是到了Python,在2.x中,异常对象可以是任何对象,经常看到很多代码是直接raise一个字符串出来,因此就不能像Java那样方便的获取异常栈了,因为异常对象和异常栈是分开的。而多数Python语言的书籍上重点在于描述Python中如何构造异常对象和raise try except finally这些的使用,对调试程序起关键作用的stacktrace往往基本上不怎么涉及。

python中用于处理异常栈的模块是traceback模块,它提供了print_exception、format_exception等输出异常栈等常用的工具函数。

def func(a, b):
    return a / b
if __name__ == '__main__':
    import sys
    import traceback
    try:
        func(1, 0)
    except Exception as e:
        print "print exc"
        traceback.print_exc(file=sys.stdout)

输出结果:

print exc
Traceback (most recent call last):
  File "./teststacktrace.py", line 7, in <module>
    func(1, 0)
  File "./teststacktrace.py", line 2, in func
    return a / b

其实traceback.print_exc()函数只是traceback.print_exception()函数的一个简写形式,而它们获取异常相关的数据都是通过sys.exc_info()函数得到的。

def func(a, b):
    return a / b
if __name__ == '__main__':
    import sys
    import traceback
    try:
        func(1, 0)
    except Exception as e:
        print "print_exception()"
        exc_type, exc_value, exc_tb = sys.exc_info()
        print 'the exc type is:', exc_type
        print 'the exc value is:', exc_value
        print 'the exc tb is:', exc_tb
        traceback.print_exception(exc_type, exc_value, exc_tb)

输出结果:

print_exception()
the exc type is: <type 'exceptions.ZeroDivisionError'>
the exc value is: integer division or modulo by zero
the exc tb is: <traceback object at 0x104e7d4d0>
Traceback (most recent call last):
  File "./teststacktrace.py", line 7, in <module>
    func(1, 0)
  File "./teststacktrace.py", line 2, in func
    return a / b
ZeroDivisionError: integer division or modulo by zero

sys.exc_info()返回的值是一个元组,其中第一个元素,exc_type是异常的对象类型,exc_value是异常的值,exc_tb是一个traceback对象,对象中包含出错的行数、位置等数据。然后通过print_exception函数对这些异常数据进行整理输出。
traceback模块提供了extract_tb函数来更加详细的解释traceback对象所包含的数据:

def func(a, b):
    return a / b
if __name__ == '__main__':
    import sys
    import traceback
    try:
        func(1, 0)
    except:
        _, _, exc_tb = sys.exc_info()
        for filename, linenum, funcname, source in traceback.extract_tb(exc_tb):
            print "%-23s:%s '%s' in %s()" % (filename, linenum, source, funcname)

输出结果:

samchimac:tracebacktest samchi$ python ./teststacktrace.py 
./teststacktrace.py    :7 'func(1, 0)' in <module>()
./teststacktrace.py    :2 'return a / b' in func()

2.使用cgitb来简化异常调试
如果平时开发喜欢基于log的方式来调试,那么可能经常去做这样的事情,在log里面发现异常之后,因为信息不足,那么会再去额外加一些debug log来把相关变量的值输出。调试完毕之后再把这些debug log去掉。其实没必要这么麻烦,Python库中提供了cgitb模块来帮助做这些事情,它能够输出异常上下文所有相关变量的信息,不必每次自己再去手动加debug log。
cgitb的使用简单的不能想象:

def func(a, b):
    return a / b
if __name__ == '__main__':
    import cgitb
    cgitb.enable(format='text')
    import sys
    import traceback
    func(1, 0)

运行之后就会得到详细的数据:

A problem occurred in a Python script.  Here is the sequence of

function calls leading up to the error, in the order they occurred.

 /Users/samchi/Documents/workspace/tracebacktest/teststacktrace.py in <module>()
    4     import cgitb
    5     cgitb.enable(format='text')
    6     import sys
    7     import traceback
    8     func(1, 0)
func = <function func>

 /Users/samchi/Documents/workspace/tracebacktest/teststacktrace.py in func(a=1, b=0)
    2     return a / b
    3 if __name__ == '__main__':
    4     import cgitb
    5     cgitb.enable(format='text')
    6     import sys
a = 1
b = 0

完全不必再去log.debug("a=%d" % a)了,个人感觉cgitb在线上环境不适合使用,适合在开发的过程中进行调试,非常的方便。
也许你会问,cgitb为什么会这么屌?能获取这么详细的出错信息?其实它的工作原理同它的使用方式一样的简单,它只是覆盖了默认的sys.excepthook函数,sys.excepthook是一个默认的全局异常拦截器,可以尝试去自行对它修改:

def func(a, b):
    return a / b
def my_exception_handler(exc_type, exc_value, exc_tb):
    print "i caught the exception:", exc_type
    while exc_tb:
            print "the line no:", exc_tb.tb_lineno
            print "the frame locals:", exc_tb.tb_frame.f_locals
            exc_tb = exc_tb.tb_next

if __name__ == '__main__':
    import sys
    sys.excepthook = my_exception_handler
    import traceback
    func(1, 0)

输出结果:

i caught the exception: <type 'exceptions.ZeroDivisionError'>
the line no: 14
the frame locals: {'my_exception_handler': <function  my_exception_handler at 0x100e04aa0>, '__builtins__': <module '__builtin__' (built-in)>, '__file__': './teststacktrace.py', 'traceback': <module 'traceback' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/traceback.pyc'>, '__package__': None, 'sys': <module 'sys' (built-in)>, 'func': <function func at 0x100e04320>, '__name__': '__main__', '__doc__': None}
the line no: 2
the frame locals: {'a': 1, 'b': 0}

看到没有?没有什么神奇的东西,只是从stack frame对象中获取的相关变量的值。frame对象中还有很多神奇的属性,就不一一探索了。

3.使用logging模块来记录异常
在使用Java的时候,用log4j记录异常很简单,只要把Exception对象传递给log.error方法就可以了,但是在Python中就不行了,如果直接传递异常对象给log.error,那么只会在log里面出现一行异常对象的值。

在Python中正确的记录Log方式应该是这样的:

logging.exception(ex)
logging.error(ex, exc_info=1) # 指名输出栈踪迹, logging.exception的内部也是包了一层此做法
logging.critical(ex, exc_info=1) # 更加严重的错误级别

python的rsa精简模块~

之前那会上班的时候,正好要用到RSA加密解密,
然后我出于偷懒的目的,所以我就百度了一个RSA的模块。
虽然python在大数运算上灰常容易,但是那个PKCS#1 v1.5想想就觉得麻烦~
所以直接用了人家的RSA模块。
介个是地址:https://pypi.python.org/pypi/rsa/
这个RSA模块真的是灰常强大啊,好厉害啊


These are some average timings from my desktop machine (Linux 2.6, 2.93 GHz quad-core Intel Core i7, 16 GB RAM) using 64-bit CPython 2.7. Since key generation is a random process, times may differ even on similar hardware. On all tests, we used the default accurate=True.

Keysize (bits)|single process|eight processes

128|0.01 sec.|0.01 sec.
256|0.03 sec.|0.02 sec.
384|0.09 sec.|0.04 sec.
512|0.11 sec.|0.07 sec.
1024|0.79 sec.|0.30 sec.
2048|6.55 sec.|1.60 sec.
3072|23.4 sec.|7.14 sec.
4096 |72.0 sec.|24.4 sec.

但是捏,由于我只做加密解密,用不到密钥的生成,所以为了加密解密带上一个包的RSA模块又觉得说不过去。
于是,在偷懒中,我对这个RSA的3.1.4版本进行了简单的精简,去除了密钥生成,只保留了加密解密部分代码,并且,将一个py包精简为一个py文件。由于很懒,所以精简的很随意,如果路过的大大们需要这样一个简单的RSALite包,就拿去吧~Tips:精简后,仍是基于PKCS#1 v1.5。

如果我的不成熟的代码能够帮到您,请[[戳我]][1]获得它

#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
#  rsalite by ino@o3or.com
#===========================================================================
#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
#===========================================================================
"""
RSALite module

Module for calculating large primes, and RSA encryption, decryption. 
not includes generating public and private keys.

"""
from __future__ import absolute_import
import sys
import binascii
import hashlib
import os
from struct import pack

__author__ = "Sybren Stuvel, Barry Mead and Yesudeep Mangalapilly | lite by ino"
__date__ = "2014-03-28"
__version__ = '3.1.4lite'

# ===========================================================================
#"""Python compatibility wrappers."""


try:
    MAX_INT = sys.maxsize
except AttributeError:
    MAX_INT = sys.maxint

MAX_INT64 = (1 << 63) - 1
MAX_INT32 = (1 << 31) - 1
MAX_INT16 = (1 << 15) - 1

# Determine the word size of the processor.
if MAX_INT == MAX_INT64:
    # 64-bit processor.
    MACHINE_WORD_SIZE = 64
elif MAX_INT == MAX_INT32:
    # 32-bit processor.
    MACHINE_WORD_SIZE = 32
else:
    # Else we just assume 64-bit processor keeping up with modern times.
    MACHINE_WORD_SIZE = 64


try:
    # < Python3
    unicode_type = unicode
    have_python3 = False
except NameError:
    # Python3.
    unicode_type = str
    have_python3 = True

# Fake byte literals.
if str is unicode_type:
    def byte_literal(s):
        return s.encode('latin1')
else:
    def byte_literal(s):
        return s

# ``long`` is no more. Do type detection using this instead.
try:
    integer_types = (int, long)
except NameError:
    integer_types = (int,)

b = byte_literal


# To avoid calling b() multiple times in tight loops.
ZERO_BYTE = b('\x00')
EMPTY_BYTE = b('')


def is_integer(obj):
    """
    Determines whether the given value is an integer.

    :param obj:
        The value to test.
    :returns:
        ``True`` if ``value`` is an integer; ``False`` otherwise.
    """
    return isinstance(obj, integer_types)

def get_word_alignment(num, force_arch=64,
                       _machine_word_size=MACHINE_WORD_SIZE):
    """
    Returns alignment details for the given number based on the platform
    Python is running on.

    :param num:
        Unsigned integral number.
    :param force_arch:
        If you don't want to use 64-bit unsigned chunks, set this to
        anything other than 64. 32-bit chunks will be preferred then.
        Default 64 will be used when on a 64-bit machine.
    :param _machine_word_size:
        (Internal) The machine word size used for alignment.
    :returns:
        4-tuple::

            (word_bits, word_bytes,
             max_uint, packing_format_type)
    """
    max_uint64 = 0xffffffffffffffff
    max_uint32 = 0xffffffff
    max_uint16 = 0xffff
    max_uint8 = 0xff

    if force_arch == 64 and _machine_word_size >= 64 and num > max_uint32:
        # 64-bit unsigned integer.
        return 64, 8, max_uint64, "Q"
    elif num > max_uint16:
        # 32-bit unsigned integer
        return 32, 4, max_uint32, "L"
    elif num > max_uint8:
        # 16-bit unsigned integer.
        return 16, 2, max_uint16, "H"
    else:
        # 8-bit unsigned integer.
        return 8, 1, max_uint8, "B"

# ===========================================================================
# '''Common functionality shared by several modules.'''


def bit_size(num):
    '''
    Number of bits needed to represent a integer excluding any prefix
    0 bits.

    As per definition from http://wiki.python.org/moin/BitManipulation and
    to match the behavior of the Python 3 API.

    Usage::
    
        >>> bit_size(1023)
        10
        >>> bit_size(1024)
        11
        >>> bit_size(1025)
        11

    :param num:
        Integer value. If num is 0, returns 0. Only the absolute value of the
        number is considered. Therefore, signed integers will be abs(num)
        before the number's bit length is determined.
    :returns:
        Returns the number of bits in the integer.
    '''
    if num == 0:
        return 0
    if num < 0:
        num = -num

    # Make sure this is an int and not a float.
    num & 1

    hex_num = "%x" % num
    return ((len(hex_num) - 1) * 4) + {
        '0':0, '1':1, '2':2, '3':2,
        '4':3, '5':3, '6':3, '7':3,
        '8':4, '9':4, 'a':4, 'b':4,
        'c':4, 'd':4, 'e':4, 'f':4,
     }[hex_num[0]]


def byte_size(number):
    '''
    Returns the number of bytes required to hold a specific long number.
    
    The number of bytes is rounded up.

    Usage::

        >>> byte_size(1 << 1023)
        128
        >>> byte_size((1 << 1024) - 1)
        128
        >>> byte_size(1 << 1024)
        129

    :param number:
        An unsigned integer
    :returns:
        The number of bytes required to hold a specific long number.
    '''
    quanta, mod = divmod(bit_size(number), 8)
    if mod or number == 0:
        quanta += 1
    return quanta
    #return int(math.ceil(bit_size(number) / 8.0))

# ===========================================================================

#'''Core mathematical operations.

#This is the actual core RSA implementation, which is only defined
#mathematically on integers.
#'''

def assert_int(var, name):

    if is_integer(var):
        return

    raise TypeError('%s should be an integer, not %s' % (name, var.__class__))

def encrypt_int(message, ekey, n):
    '''Encrypts a message using encryption key 'ekey', working modulo n'''

    assert_int(message, 'message')
    assert_int(ekey, 'ekey')
    assert_int(n, 'n')

    if message < 0:
        raise ValueError('Only non-negative numbers are supported')
     
    if message > n:
        raise OverflowError("The message %i is too long for n=%i" % (message, n))

    return pow(message, ekey, n)

def decrypt_int(cyphertext, dkey, n):
    '''Decrypts a cypher text using the decryption key 'dkey', working
    modulo n'''

    assert_int(cyphertext, 'cyphertext')
    assert_int(dkey, 'dkey')
    assert_int(n, 'n')

    message = pow(cyphertext, dkey, n)
    return message

# ===========================================================================

#'''Data transformation functions.

#From bytes to a number, number to bytes, etc.
#'''



try:
    # We'll use psyco if available on 32-bit architectures to speed up code.
    # Using psyco (if available) cuts down the execution time on Python 2.5
    # at least by half.
    import psyco
    psyco.full()
except ImportError:
    pass

def bytes2int(raw_bytes):
    r'''Converts a list of bytes or an 8-bit string to an integer.

    When using unicode strings, encode it to some encoding like UTF8 first.

    >>> (((128 * 256) + 64) * 256) + 15
    8405007
    >>> bytes2int('\x80@\x0f')
    8405007

    '''

    return int(binascii.hexlify(raw_bytes), 16)


def bytes_leading(raw_bytes, needle=ZERO_BYTE):
    '''
    Finds the number of prefixed byte occurrences in the haystack.

    Useful when you want to deal with padding.

    :param raw_bytes:
        Raw bytes.
    :param needle:
        The byte to count. Default \000.
    :returns:
        The number of leading needle bytes.
    '''
    leading = 0
    # Indexing keeps compatibility between Python 2.x and Python 3.x
    _byte = needle[0]
    for x in raw_bytes:
        if x == _byte:
            leading += 1
        else:
            break
    return leading
def int2bytes(number, fill_size=None, chunk_size=None, overflow=False):
    '''
    Convert an unsigned integer to bytes (base-256 representation)::

    Does not preserve leading zeros if you don't specify a chunk size or
    fill size.

    .. NOTE:
        You must not specify both fill_size and chunk_size. Only one
        of them is allowed.

    :param number:
        Integer value
    :param fill_size:
        If the optional fill size is given the length of the resulting
        byte string is expected to be the fill size and will be padded
        with prefix zero bytes to satisfy that length.
    :param chunk_size:
        If optional chunk size is given and greater than zero, pad the front of
        the byte string with binary zeros so that the length is a multiple of
        ``chunk_size``.
    :param overflow:
        ``False`` (default). If this is ``True``, no ``OverflowError``
        will be raised when the fill_size is shorter than the length
        of the generated byte sequence. Instead the byte sequence will
        be returned as is.
    :returns:
        Raw bytes (base-256 representation).
    :raises:
        ``OverflowError`` when fill_size is given and the number takes up more
        bytes than fit into the block. This requires the ``overflow``
        argument to this function to be set to ``False`` otherwise, no
        error will be raised.
    '''
    if number < 0:
        raise ValueError("Number must be an unsigned integer: %d" % number)

    if fill_size and chunk_size:
        raise ValueError("You can either fill or pad chunks, but not both")

    # Ensure these are integers.
    number & 1

    raw_bytes = b('')

    # Pack the integer one machine word at a time into bytes.
    num = number
    word_bits, _, max_uint, pack_type = get_word_alignment(num)
    pack_format = ">%s" % pack_type
    while num > 0:
        raw_bytes = pack(pack_format, num & max_uint) + raw_bytes
        num >>= word_bits
    # Obtain the index of the first non-zero byte.
    zero_leading = bytes_leading(raw_bytes)
    if number == 0:
        raw_bytes = ZERO_BYTE
    # De-padding.
    raw_bytes = raw_bytes[zero_leading:]

    length = len(raw_bytes)
    if fill_size and fill_size > 0:
        if not overflow and length > fill_size:
            raise OverflowError(
                "Need %d bytes for number, but fill size is %d" %
                (length, fill_size)
            )
        raw_bytes = raw_bytes.rjust(fill_size, ZERO_BYTE)
    elif chunk_size and chunk_size > 0:
        remainder = length % chunk_size
        if remainder:
            padding_size = chunk_size - remainder
            raw_bytes = raw_bytes.rjust(length + padding_size, ZERO_BYTE)
    return raw_bytes


# ===========================================================================
#'''RSA key code.

#Create new keys with the newkeys() function. It will give you a PublicKey and a
#PrivateKey object.

#Loading and saving keys requires the pyasn1 module. This module is imported as
#late as possible, such that other functionality will remain working in absence
#of pyasn1.

#'''

class PublicKey():
    '''Represents a public RSA key.

    This key is also known as the 'encryption key'. It contains the 'n' and 'e'
    values.

    Supports attributes as well as dictionary-like access. Attribute accesss is
    faster, though.

    >>> PublicKey(5, 3)
    PublicKey(5, 3)

    >>> key = PublicKey(5, 3)
    >>> key.n
    5
    >>> key['n']
    5
    >>> key.e
    3
    >>> key['e']
    3

    '''

    __slots__ = ('n', 'e')

    def __init__(self, n, e):
        self.n = n
        self.e = e

    def __getitem__(self, key):
        return getattr(self, key)

    def __repr__(self):
        return 'PublicKey(%i, %i)' % (self.n, self.e)

    def __eq__(self, other):
        if other is None:
            return False

        if not isinstance(other, PublicKey):
            return False

    return self.n == other.n and self.e == other.e

    def __ne__(self, other):
        return not (self == other)
class PrivateKey():
    '''Represents a private RSA key.

    This key is also known as the 'decryption key'. It contains the 'n', 'e',
    'd'.

    Supports attributes as well as dictionary-like access. Attribute accesss is
    faster, though.

    >>> PrivateKey(3247, 65537, 833)
    PrivateKey(3247, 65537, 833)

    '''

    __slots__ = ('n', 'e', 'd')

    def __init__(self, n, e, d):
        self.n = n
        self.e = e
        self.d = d

    def __getitem__(self, key):
        return getattr(self, key)

    def __repr__(self):
        return 'PrivateKey(%(n)i, %(e)i, %(d)i' % self

    def __eq__(self, other):
        if other is None:
            return False

        if not isinstance(other, PrivateKey):
            return False

        return (self.n == other.n and
            self.e == other.e and
            self.d == other.d)

    def __ne__(self, other):
        return not (self == other)
# ===========================================================================
#'''Functions for PKCS#1 version 1.5 encryption and signing

#This module implements certain functionality from PKCS#1 version 1.5. For a
#very clear example, read http://www.di-mgt.com.au/rsa_alg.html#pkcs1schemes

#At least 8 bytes of random padding is used when encrypting a message. This makes
#these methods much more secure than the ones in the ``rsa`` module.

#WARNING: this module leaks information when decryption or verification fails.
#The exceptions that are raised contain the Python traceback information, which
#can be used to deduce where in the process the failure occurred. DO NOT PASS
#SUCH INFORMATION to your users.
#'''

class CryptoError(Exception):
    '''Base class for all exceptions in this module.'''

class DecryptionError(CryptoError):
    '''Raised when decryption fails.'''

def _pad_for_encryption(message, target_length):
    r'''Pads the message for encryption, returning the padded message.

    :return: 00 02 RANDOM_DATA 00 MESSAGE

    >>> block = _pad_for_encryption('hello', 16)
    >>> len(block)
    16
    >>> block[0:2]
    '\x00\x02'
    >>> block[-6:]
    '\x00hello'

    '''

    max_msglength = target_length - 11
    msglength = len(message)

    if msglength > max_msglength:
        raise OverflowError('%i bytes needed for message, but there is only'
            ' space for %i' % (msglength, max_msglength))

    # Get random padding
    padding = b('')
    padding_length = target_length - msglength - 3

    # We remove 0-bytes, so we'll end up with less padding than we've asked for,
    # so keep adding data until we're at the correct length.
    while len(padding) < padding_length:
        needed_bytes = padding_length - len(padding)
    
        # Always read at least 8 bytes more than we need, and trim off the rest
        # after removing the 0-bytes. This increases the chance of getting
        # enough bytes, especially when needed_bytes is small
        new_padding = os.urandom(needed_bytes + 5)
        new_padding = new_padding.replace(b('\x00'), b(''))
        padding = padding + new_padding[:needed_bytes]

    assert len(padding) == padding_length

    return b('').join([b('\x00\x02'),
                    padding,
                    b('\x00'),
                    message])


def encrypt(message, pub_key):
    '''Encrypts the given message using PKCS#1 v1.5
    
    :param message: the message to encrypt. Must be a byte string no longer than
        ``k-11`` bytes, where ``k`` is the number of bytes needed to encode
        the ``n`` component of the public key.
    :param pub_key: the :py:class:`rsa.PublicKey` to encrypt with.
    :raise OverflowError: when the message is too large to fit in the padded
        block.
    
    >>> pub_key = PublicKey(n, e)
    >>> message = 'hello'
    >>> crypto = encrypt(message, pub_key)
    
    The crypto text should be just as long as the public key 'n' component:


    '''

    keylength = byte_size(pub_key.n)
    padded = _pad_for_encryption(message, keylength)

    payload = bytes2int(padded)
    encrypted = encrypt_int(payload, pub_key.e, pub_key.n)
    block = int2bytes(encrypted, keylength)

    return block

def decrypt(crypto, priv_key):
    r'''Decrypts the given message using PKCS#1 v1.5

    The decryption is considered 'failed' when the resulting cleartext doesn't
    start with the bytes 00 02, or when the 00 byte between the padding and
    the message cannot be found.

    :param crypto: the crypto text as returned by :py:func:`rsa.encrypt`
    :param priv_key: the :py:class:`rsa.PrivateKey` to decrypt with.
    :raise DecryptionError: when the decryption fails. No details are given as
        to why the code thinks the decryption fails, as this would leak
        information about the private key.

    >>> pub_key = PublicKey(n, e)
    >>> priv_key = PrivateKey(n,e,d)

    It works with strings:

    >>> crypto = encrypt('hello', pub_key)
    >>> decrypt(crypto, priv_key)
    'hello'

    And with binary data:

    >>> crypto = encrypt('\x00\x00\x00\x00\x01', pub_key)
    >>> decrypt(crypto, priv_key)
    '\x00\x00\x00\x00\x01'
    .. warning::

        Never display the stack trace of a
        :py:class:`rsa.pkcs1.DecryptionError` exception. It shows where in the
        code the exception occurred, and thus leaks information about the key.
        It's only a tiny bit of information, but every bit makes cracking the
        keys easier.

    >>> crypto = encrypt('hello', pub_key)
    >>> crypto = crypto[0:5] + 'X' + crypto[6:] # change a byte
    >>> decrypt(crypto, priv_key)
    Traceback (most recent call last):
    ...
    DecryptionError: Decryption failed

    '''

    blocksize = byte_size(priv_key.n)
    encrypted = bytes2int(crypto)
    decrypted = decrypt_int(encrypted, priv_key.d, priv_key.n)
    cleartext = int2bytes(decrypted, blocksize)

    # If we can't find the cleartext marker, decryption failed.
    if cleartext[0:2] != b('\x00\x02'):
        raise DecryptionError('Decryption failed')

    # Find the 00 separator between the padding and the message
    try:
        sep_idx = cleartext.index(b('\x00'), 2)
    except ValueError:
        raise DecryptionError('Decryption failed')

    return cleartext[sep_idx+1:]
# ===========================================================================

大概就是这个样子啦(✿◡‿◡)
额,下面放一个简单的应用示例:
因为RSA加密后不一定是可读的,所以在这个例子里,我在RSA后加了一个base64为了方便显示传输~

# /usr/bin/env python
#-*- coding:utf8 -*-

import rsalite
import base64
import datetime
"""
rsalite pkcs#1 v1.5 + base64
"""

def encrypt(message, n, e):
    pub_key = rsalite.PublicKey(n, e)
    return base64.b64encode(rsalite.encrypt(message, pub_key))

def decrypt(crypto, n, e, d):
    priv_key = rsalite.PrivateKey(n, e, d)
    return rsalite.decrypt(base64.b64decode(crypto), priv_key)

if __name__=="__main__":
    message = "睡个午觉好咯"
    n = 110945963084729473086130203053960579550327729658653847757740988437942109564961023146972997505984588276879603057313266311940033330197319153582130175907476828376116030185974931539273268251822428164938194795044377834219803829324792738562530352716088675074468303811597376036491268631231669325065321536138026294537
    e = 65537
    d = 30172114989382080333461992600069264832468546404415635878758832978766837340377196324953838816991368491978960973045674130303602759419973744210053956165203764840228493876500545273584837106269531589946013642765942133471280266654547841324173913630308073510056590061826558556761211357514740191416959593086511172993
    crypto = encrypt(message, n, e)
    print "A :", message
    print "B :", crypto
    print "A~:", decrypt(crypto, n, e, d)
    

未闻花名

清明将至,有点开心不起来的样子。
每天有人离去、有人降临。
时间却是无关的继续行走。
可是,又能记住谁的谁呢。
来到之前、离开之后的世界是什么样子,
无人知晓、却是春来到..
未闻花名


害羞的shell

0.0今天上班后,给FWQ更新程序,然后恢复程序的后台运行。
程序的工作是监听8000端口。
然后死活啊,后台启动完程序,一查端口监听,嗯,好滴,8000在被监听~
然后开心的关了ssh的终端。
然后尼玛一查,我去,QAQ监听没了、进程也没了。
百思不得其解啊,我究竟招谁惹谁了。
好吧~
后来终于发现原因了,QAQ我每次关终端,都是暴利的直接xx掉的。
然后进程啊、端口监听啊,就没了。
然后我发现,如果我温柔的用exit离开FWQ,进程就活的好好地。
(ー`´ー)哼,神马玩意!!!
shell你说你没事害羞个啥哇~


兜兜转转的豆瓣

这么快就1年多的时间过去了。
今天终于又在豆瓣上注册了。
想当初毕业那会,因为一直在用python嘛,就想找个和python相关的工作,然后第一眼看上的就是豆瓣的测试开发了。那会正好错过了她的宣讲会还是啥的,然后就发邮件寄简历来着。没想到竟然收到了回音,让我参加网上面试。
哎,网上面试真的是又坑又惊喜。。因为豆瓣是web嘛,里面的题尼玛都是跟网络相关的,我那个哭啊,有木有,你让一个成天研究算法的人,做网络题,杀了我吧~不过,喜的是里面有一道编辑距离的算法题。这简直就是送分啊。好吧,虽然成绩不好,还是给了面试的机会。
QAQ恩,人生的第一次面试,我不想说了,在我看来,那就是压力面试的压力面试版。QAQ我承认我没好好背概念,我承认我背了也记不住,但是,哎,那次面试真的是惨坏了,有木有。然后不出意外的就是over了。打那之后,有关豆瓣的应用我都绕着走啊,(惹不起还躲不起么#)好吧,这么一躲,躲了1年多。
其实,还是很喜欢豆瓣的,真的,那时候豆瓣刚出来的时候,在各种厚重的网站之中,豆瓣就像是春天的小清新,惹人喜爱。奈何咱脸皮薄、技术差呢。嘿嘿~
今天也不知道怎么了,在刷github刷不开刷不开之后,神来之笔的来了豆瓣,神来之笔的注册了。好吧,估计是好了伤疤忘了疼。哎,又爱又恨啊。
最近想去学点什么,跟计算机无关的。总觉得天天上班用电脑,回家渣电脑,再好的夫妻也有疲劳期啊。( ⊙ o ⊙ )!水开了,我去也~


3月末-4月5日

  1. 软考1-3章 相关内容掌握。
    计算机系统知识、程序语言基础知识、操作系统知识。
  2. 测试点列表。
    手机那个倒霉的UI唷~
  3. RSA加密。
    RSA加密in python、pkcs1 v1.5

→3.29已完成RSALite,从RSA模块中精简出了RSA加密解密算法,抛弃掉密钥生成~

  1. GIF动画~
    首页上的动画咯

QAQ好想打酱油...


纷纷扰扰

很久没有动手写点什么了,
之前一直在纠结要不要阿里云一把~
不过这个念头还是放弃了~
实在是没有功夫弄备案and最近真的是好忙啊。
其实想要的不多,便在这好了~

之前有说,春天好多人走离职了。
还是有伤感。
便一直那那句“何处惹尘埃”劝解自己。
好吧 好吧...
写这些话的时候,马航出结果了。
虽然还是那个不好的结果,大飞机 要找到了么?

恩,离睡觉还有五分钟,说说最近干了啥吧。
写文档、分析数据、捣鼓webQQ、RSA算法,望天 还有啥。
哦,还有睡觉=-= 感冒~看MM。
晚安night...


somehow somewhere

好像开春公司走了好多人。
默默的就走了...

最近有点忙,但是突然觉得放松了。
之前一直懒得写东西
哎,原来的好多计划都搁置了。。
想弄个vps啥的0.0
最近穷啊~~~

好吧,我打算捡捡之前计划了。。


时光机、星星索

夜一点一点的深了。
说着不要想不要想。
止不住的泪水流下。

我想着一起数不清的日日夜夜。
曾经觉得满不在乎的一点一滴。
听他们背后吐槽你的偷偷窃喜。
还有偶然惹你生气的小小得意。

如果有时光机多好,
若能回到去年多好,
在达到前能改变多好,
总是说着回不去了,
却也真的回不去了。

要加油...

几米
---------------------------------------------------------------------------几米----------------------------------------


发散思维

我需要发散发散思维,最近有点僵了。
今晚的效率还不错,确实想清楚了一些问题。
晚安~