空谷幽兰

潮湿的空气透出草的腥香,下过雨的天空格外的蓝。
云开了云散了,风儿赶着云快跑。
细小的尘埃沿着透过树荫洒下的光柱跳舞。
工人们手中浇灌绿化的水柱在阳光下开出七彩的光辉。
情侣们拉着手亲昵着逛着街,留下鞋跟响起的踢踢踏踏。
打着旋的茶叶漂浮在碗中,
我猫在角落里关注这一切,不近不远...
曰:一花一世界,一木一浮生。

空谷幽兰
banner1 ↑ 5.3.2014
空谷幽兰2
banner2 ↑ 5.25.2014


Daily Growing

最近公司里天天就像是桑拿房,一个个脾气都不好。
忽然的,就萌生了退意。
天天早上跟我说,之前告诉我的需求又有了新的变化。
然后就是查程序,加方法。
day after day
各种内心不淡定啊,敢一次说完了么~
然后就不淡定的在豆瓣上刷FM,突然的就喜欢上了Alten的歌。
改程序的时候,听着daily growing突然就哭了。
其实歌词倒是没太大听懂,就是觉得悠扬的曲子有种莫名的悲伤。
恩,就是很莫名。
就像是我站在9楼的窗前,总是有种想跳下去的冲动,
倒不是想不开,就是突然变得很想飞,很想要自由~


与编辑距离有关

最近几天在整理以前收集的和用过有点忘记的编程、算法等相关信息。
当初毕设做的字符串测试数据自动生成算法中就是应用了编辑距离,那会捯饬这个浪费了不少时间。
所谓编辑距离,是指两个任意字符串s, t。由s经过编辑操作编程t所需的操作次数,这里的编辑操作包括插入、替换、删除三种操作。
由此,两个字符串之间的编辑距离可以定义为:

ED(s:a,t:b)=min(ED(s:a,t)+1,ED(s,t:b)+1,ED(s,t)+ED(a,b))

在这里,s, t是两个可能为空的字符串;s:a,t:b是字符串s,t的子串;a,b为字符。如果两个字符串均为空,则它们的编辑距离是0;一个非空字符串和空字符串的编辑距离是非空字符串的长度。
0.0 介个是编辑距离相关的信息,恩,如果用程序实现计算编辑距离肿么做呢。
可以用动态规划来实现编辑距离~

首先定义这样一个函数——edit(i, j),它表示第一个字符串的长度为i的子串到第二个字符串的长度为j的子串的编辑距离。
显然可以有如下动态规划公式:

  • if i == 0 且 j == 0,edit(i, j) = 0
  • if i == 0 且 j > 0,edit(i, j) = j
  • if i > 0 且j == 0,edit(i, j) = i
  • if i ≥ 1 且 j ≥ 1 ,edit(i, j) == min{ edit(i-1, j) + 1, edit(i, j-1) + 1, edit(i-1, j-1) + f(i, j) },当第一个字符串的第i个字符不等于第二个字符串的第j个字符时,f(i, j) = 1;否则,f(i, j) = 0。

那算法就是这样,譬如可以有如下一个示例。串A:GUMBO,串B:GAMBOL,计算它们之间的编辑距离。

Steps 1 and 2
= = G U M B O
= 0 1 2 3 4 5
G 1
A 2
M 3
B 4
O 5
L 6

Steps 3 to 6 When i = 1
= = G U M B O
= 0 1 2 3 4 5
G 1 0
A 2 1
M 3 2
B 4 3
O 5 4
L 6 5

Steps 3 to 6 When i = 2
= = G U M B O
= 0 1 2 3 4 5
G 1 0 1
A 2 1 1
M 3 2 2
B 4 3 3
O 5 4 4
L 6 5 5

Steps 3 to 6 When i = 3
= = G U M B O
= 0 1 2 3 4 5
G 1 0 1 2
A 2 1 1 2
M 3 2 2 1
B 4 3 3 2
O 5 4 4 3
L 6 5 5 4

Steps 3 to 6 When i = 4
= = G U M B O
= 0 1 2 3 4 5
G 1 0 1 2 3
A 2 1 1 2 3
M 3 2 2 1 2
B 4 3 3 2 1
O 5 4 4 3 2
L 6 5 5 4 3

Steps 3 to 6 When i = 5
= = G U M B O
= 0 1 2 3 4 5
G 1 0 1 2 3 4
A 2 1 1 2 3 4
M 3 2 2 1 2 3
B 4 3 3 2 1 2
O 5 4 4 3 2 1
L 6 5 5 4 3 2

Step 7
所以,A、B之间的编辑距离最右下角的数字,即edit(A,B)=2。

算法说完了,最后说一下python中的具体实现。其实,实现的代码真的是灰常简单,(⊙v⊙)嗯,闲言碎语不要讲,直接附代码~

#! /usr/bin/env python
# -*- coding: utf-8 -*

def edit_dis(m,n):
    """
    动态规划算法,计算编辑距离,操作包括插入、删除、替换
    simple input:
    >>> print edit_dis("abc","abec")
    1
    >>> print edit_dis("ababec","abc")
    3
    """
    len_1=lambda x:len(x)+1

    c=[[i] for i in range(0,len_1(m)) ]
    c[0]=[j for j in range(0,len_1(n))]

    for i in range(0,len(m)):
        for j in range(0,len(n)):
            c[i+1].append(
                min(
                    c[i][j+1]+1, # 插入操作
                    c[i+1][j]+1, # 删除操作
                    c[i][j] + (0 if m[i]==n[j] else 1 ) # 替换操作
                )
            )
    return c[-1][-1]

if __name__ == '__main__':
    print edit_dis("abc","abedfsfc")

恩,就酱~


给明年的自己。

今年的生日过的平平淡淡。
没有电话、没有蛋糕、没有祝贺。
其实这样无声无息也好。
这样特别的日子,也不想随便吐槽啥。
感觉时间过得蛮快的,这又马上老了一岁。
感觉满脑子回想的还是去年的故事。
公司里最近感觉人心惶惶的,貌似很多人都有了走的想法。
不知道为什么,感觉现在的项目就像是一个烂泥潭一样,越看问题越多。
→_→好吧,我一直告诉自己说要咬牙要坚持,程序员嘛,要写的出代码、耐的住寂寞。
不过啊,如果现在比较熟的人都走了,真不知道自己还能如此耐得住性子么?
吐槽到这,就想起来了,近2年最大的愿望有俩,1是在github中创建出自己的项目、最好是跟自动化测试相关的。2呢是,QAQ我目前最深切的怨念,我要努力好好学习,当下一次找工作的时候,我要再次投豆瓣,然后要去鄙视回去那次虐杀我的面试官,吐槽死他~(不过基友一直说,这个愿望不太现实哈)
嘛,好吧,这种事还是望望天算上一卦吧。
最后,happy brithday to myself....


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。

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

#! /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加密解密算法,抛弃掉密钥生成~

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


QAQ好想打酱油...