RSA加密需要用到质数
1 # Prime Number Sieve 2 # http://inventwithpython.com/hacking (BSD Licensed) 3 4 import math 5 6 7 def isPrime(num): 8 # Returns True if num is a prime number, otherwise False. 9 10 # Note: Generally, isPrime() is slower than primeSieve(). 11 12 # all numbers less than 2 are not prime 13 if num < 2: 14 return False 15 16 # see if num is divisible by any number up to the square root of num 17 for i in range(2, int(math.sqrt(num)) + 1): 18 if num % i == 0: 19 return False 20 return True 21 22 23 def primeSieve(sieveSize): 24 # Returns a list of prime numbers calculated using 25 # the Sieve of Eratosthenes algorithm. 26 27 sieve = [True] * sieveSize 28 sieve[0] = False # zero and one are not prime numbers 29 sieve[1] = False 30 31 # create the sieve 32 for i in range(2, int(math.sqrt(sieveSize)) + 1): 33 pointer = i * 2 34 while pointer < sieveSize: 35 sieve[pointer] = False 36 pointer += i 37 38 # compile the list of primes 39 primes = [] 40 for i in range(sieveSize): 41 if sieve[i] == True: 42 primes.append(i) 43 44 return primes
两个函数,第一个是常规的质数判断。第二个是埃拉托色尼筛选法
方法:
- (1)先把1删除(现今数学界1既不是质数也不是合数)
- (2)读取队列中当前最小的数2,然后把2的倍数删去
- (3)读取队列中当前最小的数3,然后把3的倍数删去
- (4)读取队列中当前最小的数5,然后把5的倍数删去
- (5)读取队列中当前最小的数7,然后把7的倍数删去
- (6)如上所述直到需求的范围内所有的数均删除或读取
检测较大质数——拉宾米勒质数检验,运用高等数学,且并非万无一失
1 # Primality Testing with the Rabin-Miller Algorithm 2 # http://inventwithpython.com/hacking (BSD Licensed) 3 4 import random 5 6 7 def rabinMiller(num): 8 # Returns True if num is a prime number. 9 10 s = num - 1 11 t = 0 12 while s % 2 == 0: 13 # keep halving s until it is even (and use t 14 # to count how many times we halve s) 15 s = s // 2 16 t += 1 17 18 for trials in range(5): # try to falsify num's primality 5 times 19 a = random.randrange(2, num - 1) 20 v = pow(a, s, num) 21 if v != 1: # this test does not apply if v is 1. 22 i = 0 23 while v != (num - 1): 24 if i == t - 1: 25 return False 26 else: 27 i = i + 1 28 v = (v ** 2) % num 29 return True 30 31 32 def isPrime(num): 33 # Return True if num is a prime number. This function does a quicker 34 # prime number check before calling rabinMiller(). 35 36 if (num < 2): 37 return False # 0, 1, and negative numbers are not prime 38 39 # About 1/3 of the time we can quickly determine if num is not prime 40 # by dividing by the first few dozen prime numbers. This is quicker 41 # than rabinMiller(), but unlike rabinMiller() is not guaranteed to 42 # prove that a number is prime. 43 lowPrimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997] 44 45 if num in lowPrimes: 46 return True 47 48 # See if any of the low prime numbers can divide num 49 for prime in lowPrimes: 50 if (num % prime == 0): 51 return False 52 53 # If all else fails, call rabinMiller() to determine if num is a prime. 54 return rabinMiller(num) 55 56 57 def generateLargePrime(keysize=1024): 58 # Return a random prime number of keysize bits in size. 59 while True: 60 num = random.randrange(2**(keysize-1), 2**(keysize)) 61 if isPrime(num): 62 return num
简单RSA加密范例:
1 # RSA Key Generator 2 # http://inventwithpython.com/hacking (BSD Licensed) 3 4 import random, sys, os, rabinMiller, cryptomath 5 6 7 def main(): 8 # create a public/private keypair with 1024 bit keys 9 print('Making key files...') 10 makeKeyFiles('al_sweigart', 1024) 11 print('Key files made.') 12 13 def generateKey(keySize): 14 # Creates a public/private key pair with keys that are keySize bits in 15 # size. This function may take a while to run. 16 17 # Step 1: Create two prime numbers, p and q. Calculate n = p * q. 18 print('Generating p prime...') 19 p = rabinMiller.generateLargePrime(keySize) 20 print('Generating q prime...') 21 q = rabinMiller.generateLargePrime(keySize) 22 n = p * q 23 24 # Step 2: Create a number e that is relatively prime to (p-1)*(q-1). 25 print('Generating e that is relatively prime to (p-1)*(q-1)...') 26 while True: 27 # Keep trying random numbers for e until one is valid. 28 e = random.randrange(2 ** (keySize - 1), 2 ** (keySize)) 29 if cryptomath.gcd(e, (p - 1) * (q - 1)) == 1: 30 break 31 32 # Step 3: Calculate d, the mod inverse of e. 33 print('Calculating d that is mod inverse of e...') 34 d = cryptomath.findModInverse(e, (p - 1) * (q - 1)) 35 36 publicKey = (n, e) 37 privateKey = (n, d) 38 39 print('Public key:', publicKey) 40 print('Private key:', privateKey) 41 42 return (publicKey, privateKey) 43 44 45 def makeKeyFiles(name, keySize): 46 # Creates two files 'x_pubkey.txt' and 'x_privkey.txt' (where x is the 47 # value in name) with the the n,e and d,e integers written in them, 48 # delimited by a comma. 49 50 # Our safety check will prevent us from overwriting our old key files: 51 if os.path.exists('%s_pubkey.txt' % (name)) or os.path.exists('%s_privkey.txt' % (name)): 52 sys.exit('WARNING: The file %s_pubkey.txt or %s_privkey.txt already exists! Use a different name or delete these files and re-run this program.' % (name, name)) 53 54 publicKey, privateKey = generateKey(keySize) 55 56 print() 57 print('The public key is a %s and a %s digit number.' % (len(str(publicKey[0])), len(str(publicKey[1])))) 58 print('Writing public key to file %s_pubkey.txt...' % (name)) 59 fo = open('%s_pubkey.txt' % (name), 'w') 60 fo.write('%s,%s,%s' % (keySize, publicKey[0], publicKey[1])) 61 fo.close() 62 63 print() 64 print('The private key is a %s and a %s digit number.' % (len(str(publicKey[0])), len(str(publicKey[1])))) 65 print('Writing private key to file %s_privkey.txt...' % (name)) 66 fo = open('%s_privkey.txt' % (name), 'w') 67 fo.write('%s,%s,%s' % (keySize, privateKey[0], privateKey[1])) 68 fo.close() 69 70 71 # If makeRsaKeys.py is run (instead of imported as a module) call 72 # the main() function. 73 if __name__ == '__main__': 74 main()
1 # RSA Cipher 2 # http://inventwithpython.com/hacking (BSD Licensed) 3 4 import sys 5 6 # IMPORTANT: The block size MUST be less than or equal to the key size! 7 # (Note: The block size is in bytes, the key size is in bits. There 8 # are 8 bits in 1 byte.) 9 DEFAULT_BLOCK_SIZE = 128 # 128 bytes 10 BYTE_SIZE = 256 # One byte has 256 different values. 11 12 def main(): 13 # Runs a test that encrypts a message to a file or decrypts a message 14 # from a file. 15 filename = 'encrypted_file.txt' # the file to write to/read from 16 mode = 'encrypt' # set to 'encrypt' or 'decrypt' 17 18 if mode == 'encrypt': 19 message = '''"Journalists belong in the gutter because that is where the ruling classes throw their guilty secrets." -Gerald Priestland "The Founding Fathers gave the free press the protection it must have to bare the secrets of government and inform the people." -Hugo Black''' 20 pubKeyFilename = 'al_sweigart_pubkey.txt' 21 print('Encrypting and writing to %s...' % (filename)) 22 encryptedText = encryptAndWriteToFile(filename, pubKeyFilename, message) 23 24 print('Encrypted text:') 25 print(encryptedText) 26 27 elif mode == 'decrypt': 28 privKeyFilename = 'al_sweigart_privkey.txt' 29 print('Reading from %s and decrypting...' % (filename)) 30 decryptedText = readFromFileAndDecrypt(filename, privKeyFilename) 31 32 print('Decrypted text:') 33 print(decryptedText) 34 35 36 def getBlocksFromText(message, blockSize=DEFAULT_BLOCK_SIZE): 37 # Converts a string message to a list of block integers. Each integer 38 # represents 128 (or whatever blockSize is set to) string characters. 39 40 messageBytes = message.encode('ascii') # convert the string to bytes 41 42 blockInts = [] 43 for blockStart in range(0, len(messageBytes), blockSize): 44 # Calculate the block integer for this block of text 45 blockInt = 0 46 for i in range(blockStart, min(blockStart + blockSize, len(messageBytes))): 47 blockInt += messageBytes[i] * (BYTE_SIZE ** (i % blockSize)) 48 blockInts.append(blockInt) 49 return blockInts 50 51 52 def getTextFromBlocks(blockInts, messageLength, blockSize=DEFAULT_BLOCK_SIZE): 53 # Converts a list of block integers to the original message string. 54 # The original message length is needed to properly convert the last 55 # block integer. 56 message = [] 57 for blockInt in blockInts: 58 blockMessage = [] 59 for i in range(blockSize - 1, -1, -1): 60 if len(message) + i < messageLength: 61 # Decode the message string for the 128 (or whatever 62 # blockSize is set to) characters from this block integer. 63 asciiNumber = blockInt // (BYTE_SIZE ** i) 64 blockInt = blockInt % (BYTE_SIZE ** i) 65 blockMessage.insert(0, chr(asciiNumber)) 66 message.extend(blockMessage) 67 return ''.join(message) 68 69 70 def encryptMessage(message, key, blockSize=DEFAULT_BLOCK_SIZE): 71 # Converts the message string into a list of block integers, and then 72 # encrypts each block integer. Pass the PUBLIC key to encrypt. 73 encryptedBlocks = [] 74 n, e = key 75 76 for block in getBlocksFromText(message, blockSize): 77 # ciphertext = plaintext ^ e mod n 78 encryptedBlocks.append(pow(block, e, n)) 79 return encryptedBlocks 80 81 82 def decryptMessage(encryptedBlocks, messageLength, key, blockSize=DEFAULT_BLOCK_SIZE): 83 # Decrypts a list of encrypted block ints into the original message 84 # string. The original message length is required to properly decrypt 85 # the last block. Be sure to pass the PRIVATE key to decrypt. 86 decryptedBlocks = [] 87 n, d = key 88 for block in encryptedBlocks: 89 # plaintext = ciphertext ^ d mod n 90 decryptedBlocks.append(pow(block, d, n)) 91 return getTextFromBlocks(decryptedBlocks, messageLength, blockSize) 92 93 94 def readKeyFile(keyFilename): 95 # Given the filename of a file that contains a public or private key, 96 # return the key as a (n,e) or (n,d) tuple value. 97 fo = open(keyFilename) 98 content = fo.read() 99 fo.close() 100 keySize, n, EorD = content.split(',') 101 return (int(keySize), int(n), int(EorD)) 102 103 104 def encryptAndWriteToFile(messageFilename, keyFilename, message, blockSize=DEFAULT_BLOCK_SIZE): 105 # Using a key from a key file, encrypt the message and save it to a 106 # file. Returns the encrypted message string. 107 keySize, n, e = readKeyFile(keyFilename) 108 109 # Check that key size is greater than block size. 110 if keySize < blockSize * 8: # * 8 to convert bytes to bits 111 sys.exit('ERROR: Block size is %s bits and key size is %s bits. The RSA cipher requires the block size to be equal to or greater than the key size. Either decrease the block size or use different keys.' % (blockSize * 8, keySize)) 112 113 114 # Encrypt the message 115 encryptedBlocks = encryptMessage(message, (n, e), blockSize) 116 117 # Convert the large int values to one string value. 118 for i in range(len(encryptedBlocks)): 119 encryptedBlocks[i] = str(encryptedBlocks[i]) 120 encryptedContent = ','.join(encryptedBlocks) 121 122 # Write out the encrypted string to the output file. 123 encryptedContent = '%s_%s_%s' % (len(message), blockSize, encryptedContent) 124 fo = open(messageFilename, 'w') 125 fo.write(encryptedContent) 126 fo.close() 127 # Also return the encrypted string. 128 return encryptedContent 129 130 131 def readFromFileAndDecrypt(messageFilename, keyFilename): 132 # Using a key from a key file, read an encrypted message from a file 133 # and then decrypt it. Returns the decrypted message string. 134 keySize, n, d = readKeyFile(keyFilename) 135 136 137 # Read in the message length and the encrypted message from the file. 138 fo = open(messageFilename) 139 content = fo.read() 140 messageLength, blockSize, encryptedMessage = content.split('_') 141 messageLength = int(messageLength) 142 blockSize = int(blockSize) 143 144 # Check that key size is greater than block size. 145 if keySize < blockSize * 8: # * 8 to convert bytes to bits 146 sys.exit('ERROR: Block size is %s bits and key size is %s bits. The RSA cipher requires the block size to be equal to or greater than the key size. Did you specify the correct key file and encrypted file?' % (blockSize * 8, keySize)) 147 148 # Convert the encrypted message into large int values. 149 encryptedBlocks = [] 150 for block in encryptedMessage.split(','): 151 encryptedBlocks.append(int(block)) 152 153 # Decrypt the large int values. 154 return decryptMessage(encryptedBlocks, messageLength, (n, d), blockSize) 155 156 157 # If rsaCipher.py is run (instead of imported as a module) call 158 # the main() function. 159 if __name__ == '__main__': 160 main()