summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSybren A. Stüvel <sybren@stuvel.eu>2018-09-16 12:05:47 +0200
committerSybren A. Stüvel <sybren@stuvel.eu>2018-09-16 12:05:47 +0200
commitae61397ce7a57969b14eb900f30b76e666170e62 (patch)
tree0d890e4af3704d793f37646906ef867d4746b861
parentad510185b54412f390f2ffcb2f8362326a1b0885 (diff)
downloadrsa-git-ae61397ce7a57969b14eb900f30b76e666170e62.tar.gz
Moved `get_word_alignment()` from `_compat.py` to `machine_size.py`
In preparation of removal of Python 2.7 support, I only want to have compatibility code for Python 2.7 in `_compat.py`, and not other kinds of 'compatibility'.
-rw-r--r--rsa/machine_size.py74
-rw-r--r--rsa/transform.py6
2 files changed, 77 insertions, 3 deletions
diff --git a/rsa/machine_size.py b/rsa/machine_size.py
new file mode 100644
index 0000000..2a871b8
--- /dev/null
+++ b/rsa/machine_size.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+#
+# 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
+#
+# https://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.
+
+"""Detection of 32-bit and 64-bit machines and byte alignment."""
+
+import sys
+
+MAX_INT = sys.maxsize
+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
+
+
+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"
diff --git a/rsa/transform.py b/rsa/transform.py
index acf044d..628d0af 100644
--- a/rsa/transform.py
+++ b/rsa/transform.py
@@ -24,8 +24,8 @@ from __future__ import absolute_import
import binascii
from struct import pack
-from rsa import common
-from rsa._compat import byte, is_integer, get_word_alignment
+from rsa._compat import byte, is_integer
+from rsa import common, machine_size
def bytes2int(raw_bytes):
@@ -181,7 +181,7 @@ def int2bytes(number, fill_size=None, chunk_size=None, overflow=False):
# Pack the integer one machine word at a time into bytes.
num = number
- word_bits, _, max_uint, pack_type = get_word_alignment(num)
+ word_bits, _, max_uint, pack_type = machine_size.get_word_alignment(num)
pack_format = ">%s" % pack_type
while num > 0:
raw_bytes = pack(pack_format, num & max_uint) + raw_bytes