示例#1
0
文件: crypto.py 项目: imbaczek/numbex
def parse_priv_key(privstr):
    if not isinstance(privstr, str):
        raise TypeError('str argument required')
    if not privstr.startswith('-----BEGIN DSA PRIVATE KEY-----') \
            and not privstr.startswith('-----BEGIN RSA PRIVATE KEY-----'):
        raise ValueError("public key didn't start with '-----BEGIN ANY PRIVATE KEY-----'")
    mem = BIO.MemoryBuffer(privstr)
    return DSA.load_key_bio(mem)
示例#2
0
	def payment_pta(self):
		'''Generates the Payment Transaction Authorization, or PTA. It does not communicate with the server.'''

		#------------------------------------
		#        PTA Payment Block
		#------------------------------------
		p1 = pcos.create_output_block( 'P1' )

		# member authentication token
		mat = self.args['mat'] 
		if len( mat ) != 40:
			raise RuntimeError("MAT must be 40-characters long" % self.cmd)
		p1.write_varstr( binascii.unhexlify( mat ) )

		# cert. create time and expiry
		now = long( time.time() + 0.5 )
		p1.write_ulong( now ) # certificate create-time
		p1.write_ulong( now + 24 * 3600 ) # certificate expires in 24 hrs

		# payment-limit
		(payment_int, payment_scale) = decimal_to_parts(Decimal(self.args['limit']))
		p1.write_long( payment_int ) # value
		p1.write_int( payment_scale ) # scale

		# currency
		p1.write_fixstr( "USD", size=3 )

		# recipient
		p1.write_varstr( "" )

		# ref-data
		p1.write_varstr( "" )

		# note
		p1.write_varstr( "" )

		print (" %s bytes => Payment Block" % p1.size())

		#------------------------------------
		#        PTA Signature Block
		#------------------------------------
		s1 = pcos.create_output_block( 'S1' )

		# checksum Payment Block
		digest = hashlib.sha1(p1.as_bytearray()).digest()
		
		# sign the checksum
		dsa_priv_key = BIO.MemoryBuffer( TEST_DSA_KEY_PRV_PEM )
		signer = DSA.load_key_bio( dsa_priv_key )
		signature = signer.sign_asn1( digest )

		# store the signature of the Payment Block
		s1.write_varstr( signature )
		print (" %s bytes => Signature Block" % s1.size())

		#------------------------------------
		# PTA Message
		#  * Payment Block
		#  * Signature Block
		#------------------------------------
		pta = pcos.Doc( name="Pa" )
		pta.add( p1 )
		pta.add( s1 )

		#------------------------------------
		#    A-PTA Private (PTA) Block
		#------------------------------------
		a1 = pcos.create_output_block( 'A1' )
		
		# encrypt the PTA message
		txn_pub_key = BIO.MemoryBuffer( API_TRANSACTION_KEY_PEM )
		encrypter = RSA.load_pub_key_bio( txn_pub_key )
		# RSA Encryption Scheme w/ Optimal Asymmetric Encryption Padding
		input_data = pta.as_bytearray()
		print (" %s bytes => header+meta" % (len(input_data) - s1.size() - p1.size()))
		print ("-------------\n %s bytes => Total PTA\n---------" % len(input_data))
		encrypted = encrypter.public_encrypt( pta.as_bytearray(), RSA.pkcs1_padding )
		a1.write_fixstr( encrypted, size=len(encrypted) )

		#------------------------------------
		#    A-PTA Public Block
		#------------------------------------
		k1 = pcos.create_output_block( 'K1' )
		# encryption key identifier
		k1.write_fixstr( API_TRANSACTION_KEY_ID, size=len(API_TRANSACTION_KEY_ID) )

		#------------------------------------
		#    A-PTA Message
		#------------------------------------
		apta = pcos.Doc( name="Ap" )
		apta.add( a1 )
		apta.add( k1 )
		apta_bytes = apta.as_bytearray()

		# write serialized data as binary and qr-code
		payload_file = open('apta.pcos', 'w')
		payload_file.write( apta_bytes )
		payload_file.close()
		print ("Saved APTA object to 'apta.pcos'")

		# optionally generate qr-code
		try:
			import qrcode
			qr = qrcode.QRCode(version=None, box_size=3, error_correction=qrcode.constants.ERROR_CORRECT_L)
			qr.add_data( apta_bytes )
			qr.make(fit=True)
			img = qr.make_image()
			img.save('apta.png')
			print ("APTA-QR: apta.png, version %s" % (qr.version))
		except ImportError:
			log.warn("QR-Code not written -- qrcode module not found")

		return apta_bytes
示例#3
0
	def charge(self, payment_type, payment_bytes):
		#------------------------------------
		#      Payment Block
		#------------------------------------
		payment_block = pcos.create_output_block( payment_type )

		# we use "fixstr" becase we don't want size-prefix
		payment_block.write_fixstr(payment_bytes, len(payment_bytes))

		#------------------------------------
		#      Payment Request Block
		#------------------------------------
		paymnt_req_block = pcos.create_output_block( 'R1' ) 

		# mat
		paymnt_req_block.write_varstr( binascii.unhexlify( self.args['receiver_mat'] ) )

		# ref data
		paymnt_req_block.write_varstr( '' )

		# create-time
		paymnt_req_block.write_ulong( long( time.time() + 0.5 ) )

		(charge_int, charge_scale) = decimal_to_parts(Decimal(self.args['charge']))
		paymnt_req_block.write_long( charge_int ) # value
		paymnt_req_block.write_int( charge_scale ) # scale

		# tax
		paymnt_req_block.write_bool(True) # optional indicator
		(tax_value, tax_scale) = decimal_to_parts(Decimal(self.args['tax']))
		paymnt_req_block.write_long( tax_value ) # value
		paymnt_req_block.write_int( tax_scale ) # scale

		# tip
		paymnt_req_block.write_bool(True) # optional indicator
		(tip_value, tip_scale) = decimal_to_parts(Decimal(self.args['tip']))
		paymnt_req_block.write_long( tip_value ) # value
		paymnt_req_block.write_int( tip_scale ) # scale

		# currency
		paymnt_req_block.write_fixstr( "USD", size=3 )

		# invoice ID
		paymnt_req_block.write_varstr( 'inv-123' )

		# note
		paymnt_req_block.write_varstr( 'happy meal' )

		# no geo-location available
		paymnt_req_block.write_bool(False)

		# list of purchased goods
		paymnt_req_block.write_int(0)

		#------------------------------------
		#   Payment Request Signature Block
		#------------------------------------

		paymnt_req_signature_block = pcos.create_output_block( 'S1' )

		# checksum Payment Request Block
		digest = hashlib.sha1(paymnt_req_block.as_bytearray()).digest()
		
		# sign the checksum
		dsa_priv_key = BIO.MemoryBuffer( TEST_DSA_KEY_PRV_PEM )
		signer = DSA.load_key_bio( dsa_priv_key )
		signature = signer.sign_asn1( digest )

		# store the signature of the Payment Block
		paymnt_req_signature_block.write_varstr( signature )

		#------------------------------------
		#      Payment Request Message
		#------------------------------------
		req = pcos.Doc( name="Pt" )
		req.add( paymnt_req_block )
		req.add( paymnt_req_signature_block )
		req.add( payment_block )

		res = self.send( req )
		
		# there can be two types of results: Ap or Np, depending
		# success or failure due to insufficient funds
		if res.message_id != 'Ap' and res.message_id != 'Np':
			raise RuntimeError("Unexpected payment result '%s'" % res.message_id)
		
		# read balance
		balance = res.block( 'Bo' )
		ref_data = balance.read_varstr() # ref_data
		transaction_id = balance.read_varstr() # tx-id

		if res.message_id == 'Np':
			code = er.read_uint()
			what = er.read_varstr()
			
		# exact amount given?
		if balance.read_bool():
			exact_balance = 'is'
		else:
			exact_balance = 'is greater than' 
		# amount
		value = balance.read_long() # value
		scale = balance.read_int() # scale
		balance_amount = value * math.pow(10, scale)
		# time of last update
		tm_epoch = balance.read_ulong();
		balance_asofdate = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(tm_epoch))

		if res.message_id == 'Np':
			log.warn('%s (tx_id: %s). Balance %s $%s as of %s', what, base64.b32encode(transaction_id), exact_balance, balance_amount, balance_asofdate)
		else:
			log.info('Success (tx_id: %s). Balance %s $%s as of %s', base64.b32encode(transaction_id), exact_balance, balance_amount, balance_asofdate)
示例#4
0
	def payment(self):
		'''This command generates the Payment Transaction Authorization, or PTA. It does not communicate with the server, only produces a file.'''

		#------------------
		# PTA public-block
		#------------------
		p1 = pcos.Block( 'P1', 512, 'O' )
		now = long( time.time() + 0.5 )
		p1.write_int64( now ) # certificate create-time
		p1.write_int64( now + 24 * 3600 ) # certificate expiry (in 24 hrs)
		# p1.write_int64( now + 60*2 ) # certificate expiry

		# payment-limit
		(payment_int, payment_scale) = decimal_to_parts(Decimal(self.args['limit']))
		p1.write_int64( payment_int ) # value
		p1.write_int16( payment_scale ) # scale

		# gratuity
		tip = tip_type = None
		tipv = self.args.get('tip_pct', None)
		if tipv:
			tip_type = 'P'
		else:
			tipv = self.args.get('tip_abs', None)
			if tipv:
				tip_type = 'A'

		if tipv:
			(tip_int, tip_scale) = decimal_to_parts(Decimal(tipv))
			p1.write_byte(1) # optional indicator
			p1.write_fixed_string(tip_type, size=1) # tip type (P or A)
			p1.write_int64( tip_int ) # value
			p1.write_int16( tip_scale ) # scale
		else:
			p1.write_byte(0) # optional indicator -- no tip

		p1.write_fixed_string( "USD", size=3 ) # currency
		p1.write_fixed_string( binascii.unhexlify( API_TRANSACTION_KEY_ID ), size=4 ) # key-ID

		p1.write_short_string( '', max=127 ) # receiver
		p1.write_short_string( '', max=127 ) # note

		#-------------------
		# PTA private-block
		#-------------------
		priv = pcos.Block( 'S1', 512, 'O' )

		# member authentication token
		mat = self.args['mat'] 
		if len( mat ) != 40:
			raise RuntimeError("MAT must be 40-characters long" % self.cmd)
		priv.write_fixed_string( binascii.unhexlify( self.args['mat'] ), size=20 ) # mat
		priv.write_short_string( '', max=20 ) # ref-data
		
		# sign the public-block
		#   * first, produce the checksum
		digest = hashlib.sha1(str(p1)).digest()
		
		#   * then sign the checksum
		dsa_priv_key = BIO.MemoryBuffer( TEST_DSA_KEY_PRV_PEM )
		signer = DSA.load_key_bio( dsa_priv_key )
		signature = signer.sign_asn1( digest )
		priv.write_short_string( signature, max=48 ) # signature of the pub block
		priv.write_short_string( '', max=20 ) # empty user data

		# encrypt the private-block
		txn_pub_key = BIO.MemoryBuffer( API_TRANSACTION_KEY_PEM )
		encrypter = RSA.load_pub_key_bio( txn_pub_key )
		# RSA Encryption Scheme w/ Optimal Asymmetric Encryption Padding
		encrypted = encrypter.public_encrypt( str(priv), RSA.pkcs1_oaep_padding )

		# At this point we no longer need the private object. We only attach the
		# encrypted instance.
		s1 = pcos.Block( 'S1', 512, 'O' )
		s1.write_fixed_string( encrypted, size=128 )

		#-------------------
		# PTA envelope
		#-------------------
		env = pcos.Doc( name="Pa" )
		# order in which we add blocks doesn't matter
		env.add( p1 )
		env.add( s1 )

		# write serialized data as binary and qr-code
		encoded = env.encoded()
		reqf = open('pta.pcos', 'w')
		reqf.write( encoded )
		reqf.close()
		print ("Saved PTA object to 'pta.pcos'")

		# optionally generate qr-code
		try:
			import qrcode
			qr = qrcode.QRCode(version=None, box_size=3, error_correction=qrcode.constants.ERROR_CORRECT_L)
			qr.add_data( encoded )
			qr.make(fit=True)
			img = qr.make_image()
			img.save('pta.png')
			print ("PTA-QR: pta.png, version %s" % (qr.version))
		except ImportError:
			log.warn("QR-Code not written -- qrcode module not found")

		return encoded