2012-04-03 04:50:05 -07:00

106 lines
3.8 KiB
Python

#!/usr/bin/python
# Copyright 2012 Citrix Systems, Inc. Licensed under the
# Apache License, Version 2.0 (the "License"); you may not use this
# file except in compliance with the License. Citrix Systems, Inc.
# reserves all rights not expressly granted by 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.
#
# Automatically generated by addcopyright.py at 04/03/2012
# -*- coding: ascii -*-
# Copyright (C) 2008 Dwayne C. Litzenberger <dlitz@dlitz.net>
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import sys
import threading
from Crypto.Util.randpool import RandomPool as _RandomPool
try:
import platform
except ImportError:
platform = None # Not available using Python 2.2
def _strxor(a, b):
assert len(a) == len(b)
return "".join(map(lambda x, y: chr(ord(x) ^ ord(y)), a, b))
## Find a strong random entropy source, depending on the detected platform.
## WARNING TO DEVELOPERS: This will fail on some systems, but do NOT use
## Crypto.Util.randpool.RandomPool as a fall-back. RandomPool will happily run
## with very little entropy, thus _silently_ defeating any security that
## Paramiko attempts to provide. (This is current as of PyCrypto 2.0.1).
if ((platform is not None and platform.system().lower() == 'windows') or
sys.platform == 'win32'):
# MS Windows
from paramiko import rng_win32
rng_device = rng_win32.open_rng_device()
else:
# Assume POSIX (any system where /dev/urandom exists)
from paramiko import rng_posix
rng_device = rng_posix.open_rng_device()
class StrongLockingRandomPool(object):
"""Wrapper around RandomPool guaranteeing strong random numbers.
Crypto.Util.randpool.RandomPool will silently operate even if it is seeded
with little or no entropy, and it provides no prediction resistance if its
state is ever compromised throughout its runtime. It is also not thread-safe.
This wrapper augments RandomPool by XORing its output with random bits from
the operating system, and by controlling access to the underlying
RandomPool using an exclusive lock.
"""
def __init__(self, instance=None):
if instance is None:
instance = _RandomPool()
self.randpool = instance
self.randpool_lock = threading.Lock()
self.entropy = rng_device
# Stir 256 bits of entropy from the RNG device into the RandomPool.
self.randpool.stir(self.entropy.read(32))
self.entropy.randomize()
def stir(self, s=''):
self.randpool_lock.acquire()
try:
self.randpool.stir(s)
finally:
self.randpool_lock.release()
self.entropy.randomize()
def randomize(self, N=0):
self.randpool_lock.acquire()
try:
self.randpool.randomize(N)
finally:
self.randpool_lock.release()
self.entropy.randomize()
def add_event(self, s=''):
self.randpool_lock.acquire()
try:
self.randpool.add_event(s)
finally:
self.randpool_lock.release()
def get_bytes(self, N):
self.randpool_lock.acquire()
try:
randpool_data = self.randpool.get_bytes(N)
finally:
self.randpool_lock.release()
entropy_data = self.entropy.read(N)
result = _strxor(randpool_data, entropy_data)
assert len(randpool_data) == N and len(entropy_data) == N and len(result) == N
return result
# vim:set ts=4 sw=4 sts=4 expandtab: