Example #1
0
def reset_user_invalid_keys(user, admin_rsa):
	""" Legacy, recrypts all encrypted objects with user's new pubkey(s) """
	otype, oid = ContentType.objects.get_for_model(user), user.id
	ipubs = OwnerPublicKey.inactive.filter(owner_type=otype, owner_id=oid, active=False)
	for ipub in ipubs:
		adminclearkey = PKCS1_OAEP.new(admin_rsa).decrypt(b64decode(ipub.admincipher))
		# import inactive key
		irsa = import_rsa(ipub.adminscopy, adminclearkey)
		# get matching active public key for user
		apub = OwnerPublicKey.objects.get(owner_type=otype, owner_id=oid,
							keytype=ipub.keytype, active=True)
		# import new active publickey
		apublickey = import_rsa(apub.publickey)
		# update encrypted objects encrypting via new active public key
		for encobj in EncryptedObject.objects.filter(opub=ipub):
			clearkey = PKCS1_OAEP.new(irsa).decrypt(b64decode(encobj.cipherkey))
			encobj.cipherkey = b64encode(PKCS1_OAEP.new(apublickey).encrypt(clearkey))
			encobj.opub = apub  # point encobj's opub to new pubkey
			encobj.save()
	apubs = OwnerPublicKey.objects.filter_pubkey(owner=user)
	# reset user's private keys outside their own pubkeys if any, eg. practice locations
	privs = UserPrivateKey.objects.filter(
			user=user, credtype=CRED_WEBAPP).exclude(opub__in=apubs)
	reset_keys(privs, admin_rsa)
	# and remove inactive public keys
	ipubs.delete()
Example #2
0
def reset_user_invalid_keys(user, admin_rsa):
    """ Legacy, recrypts all encrypted objects with user's new pubkey(s) """
    otype, oid = ContentType.objects.get_for_model(user), user.id
    ipubs = OwnerPublicKey.inactive.filter(owner_type=otype,
                                           owner_id=oid,
                                           active=False)
    for ipub in ipubs:
        adminclearkey = PKCS1_OAEP.new(admin_rsa).decrypt(
            b64decode(ipub.admincipher))
        # import inactive key
        irsa = import_rsa(ipub.adminscopy, adminclearkey)
        # get matching active public key for user
        apub = OwnerPublicKey.objects.get(owner_type=otype,
                                          owner_id=oid,
                                          keytype=ipub.keytype,
                                          active=True)
        # import new active publickey
        apublickey = import_rsa(apub.publickey)
        # update encrypted objects encrypting via new active public key
        for encobj in EncryptedObject.objects.filter(opub=ipub):
            clearkey = PKCS1_OAEP.new(irsa).decrypt(b64decode(
                encobj.cipherkey))
            encobj.cipherkey = b64encode(
                PKCS1_OAEP.new(apublickey).encrypt(clearkey))
            encobj.opub = apub  # point encobj's opub to new pubkey
            encobj.save()
    apubs = OwnerPublicKey.objects.filter_pubkey(owner=user)
    # reset user's private keys outside their own pubkeys if any, eg. practice locations
    privs = UserPrivateKey.objects.filter(
        user=user, credtype=CRED_WEBAPP).exclude(opub__in=apubs)
    reset_keys(privs, admin_rsa)
    # and remove inactive public keys
    ipubs.delete()
Example #3
0
def upgrade_admin_reset_key(creds):
    """ Upgrade admin reset rsa keypair storing in _admin_reset.py. Upgraded
	public rsa keypart is stored in standard PEM format, encrypted private
	rsa keypart stored AES encrypted using CBC mode in base64 with no pickle.
	"""
    aes = AES.new(strengthen_key(creds))
    admin_kp = aes.decrypt(b64decode(settings.CRYPTO_ADMIN_KEYPAIR))
    try:
        admin_rsa = loads(admin_kp)
        admin_rsa._randfunc = os.urandom  # pickled diffs pycrypto 2.3<-->2.6
        # public key exported PEM format
        pub = export_rsa(admin_rsa.publickey())
        priv = export_rsa(admin_rsa, strengthen_key(creds))
        # put file in parent MHLogin directory
        fname = join(settings.INSTALLATION_PATH, '_admin_reset.py')
        f = open(fname, 'wb')
        f.write(ADMIN_RESET_PY % {
            'admin_public_rsa': pub,
            'admin_rsa': priv,
        })
        f.close()
        # sanity check upgrade:
        from MHLogin._admin_reset import ADMIN_RESET_PUBLIC_RSA, ADMIN_RESET_ENCD_RSA
        upgrade_rsa_pub = import_rsa(ADMIN_RESET_PUBLIC_RSA)
        assert upgrade_rsa_pub.publickey() == admin_rsa.publickey(
        ), "public key mismatch"
        upgrade_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, strengthen_key(creds))
        assert upgrade_rsa == admin_rsa, "rsa key mismatch"
        sys.stderr.write("Admin RSA reset keys upgraded in: %s\n" % fname)
    except UnpicklingError:
        sys.stderr.write("Invalid password.\n")
Example #4
0
def upgrade_admin_reset_key(creds):
	""" Upgrade admin reset rsa keypair storing in _admin_reset.py. Upgraded
	public rsa keypart is stored in standard PEM format, encrypted private
	rsa keypart stored AES encrypted using CBC mode in base64 with no pickle.
	"""
	aes = AES.new(strengthen_key(creds))
	admin_kp = aes.decrypt(b64decode(settings.CRYPTO_ADMIN_KEYPAIR))
	try:
		admin_rsa = loads(admin_kp)
		admin_rsa._randfunc = os.urandom  # pickled diffs pycrypto 2.3<-->2.6
		# public key exported PEM format
		pub = export_rsa(admin_rsa.publickey())
		priv = export_rsa(admin_rsa, strengthen_key(creds))
		# put file in parent MHLogin directory
		fname = join(settings.INSTALLATION_PATH, '_admin_reset.py')
		f = open(fname, 'wb')
		f.write(ADMIN_RESET_PY % {'admin_public_rsa': pub, 'admin_rsa': priv, })
		f.close()
		# sanity check upgrade:
		from MHLogin._admin_reset import ADMIN_RESET_PUBLIC_RSA, ADMIN_RESET_ENCD_RSA
		upgrade_rsa_pub = import_rsa(ADMIN_RESET_PUBLIC_RSA)
		assert upgrade_rsa_pub.publickey() == admin_rsa.publickey(), "public key mismatch"
		upgrade_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, strengthen_key(creds))
		assert upgrade_rsa == admin_rsa, "rsa key mismatch"
		sys.stderr.write("Admin RSA reset keys upgraded in: %s\n" % fname)
	except UnpicklingError:
		sys.stderr.write("Invalid password.\n")
Example #5
0
	def test_key_pair_fetch(self):
		""" Just for fun, normally using RSA for AES key en/decryption. """
		cleartext = 'Something fishy...'
		user = MHLUser.objects.get(username=self.provider.user.username)

		opub = OwnerPublicKey.objects.get_pubkey(owner=user)
		upriv = UserPrivateKey.objects.get_privkey(user=user, opub=opub)
		# we store keys in PEM format so import
		pubkey = import_rsa(upriv.opub.publickey)
		rsa = import_rsa(upriv.privatekey, strengthen_key(settings.SECRET_KEY if
			upriv.gfather else 'healme'))
		# pubkey enc/dec low level, PKCS1_OAEP w/RSA in production
		ciphertext = pubkey.encrypt(cleartext, os.urandom)[0]
		decrypted_text = rsa.decrypt(ciphertext)
		self.assertEqual(cleartext, decrypted_text)
Example #6
0
def reset_private_keys(request):
	"""
	This view takes the KMS administrator password, and for each user whose
	password was reset, generates new private keys.

	:param request: The HTTP request
	:type request: django.core.handlers.wsgi.WSGIRequest  
	:returns: django.http.HttpResponse -- The webpage 
	"""
	context, resp = get_context(request), None
	log_qs = PasswordResetLog.objects.filter(reset=True, resolved=False).values('user')
	reset_users = context['reset_users'] = MHLUser.objects.filter(pk__in=log_qs)

	if request.method == 'POST':
		form = context['form'] = PasswordForm(request.POST)
		if form.is_valid():
			try:
				from MHLogin._admin_reset import ADMIN_RESET_ENCD_RSA
				creds = strengthen_key(form.cleaned_data['password'])
				admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds)
			except ValueError:
				msg = _('Invalid password for admin reset key.')
				form._errors['password'] = form.error_class([msg])
			else:
				for user in reset_users:
					reset_user_invalid_keys(user, admin_rsa)
					PasswordResetLog.objects.filter(reset=True, resolved=False,
							user=user).update(resolved=True, servicer=request.user,
							servicer_ip=request.META['REMOTE_ADDR'],
							resolution_timestamp=datetime.datetime.now())
				resp = render_to_response('PrivateKeyResetComplete.html', context)
	else:
		context['form'] = PasswordForm()

	return resp or render_to_response('PrivateKeyReset.html', context)
Example #7
0
    def test_key_pair_fetch(self):
        """ Just for fun, normally using RSA for AES key en/decryption. """
        cleartext = 'Something fishy...'
        user = MHLUser.objects.get(username=self.provider.user.username)

        opub = OwnerPublicKey.objects.get_pubkey(owner=user)
        upriv = UserPrivateKey.objects.get_privkey(user=user, opub=opub)
        # we store keys in PEM format so import
        pubkey = import_rsa(upriv.opub.publickey)
        rsa = import_rsa(
            upriv.privatekey,
            strengthen_key(settings.SECRET_KEY if upriv.gfather else 'healme'))
        # pubkey enc/dec low level, PKCS1_OAEP w/RSA in production
        ciphertext = pubkey.encrypt(cleartext, os.urandom)[0]
        decrypted_text = rsa.decrypt(ciphertext)
        self.assertEqual(cleartext, decrypted_text)
Example #8
0
	def test_static_reset(self):
		# new way will obsolete test_gen_new_keys when rm #2115 in
		cleartext = "We never really grow up, we only learn how to act in public."
		c = self.client
		# after successful login should get re-direct to /
		response = c.post('/login/', {'username': '******', 'password': '******'})
		c.COOKIES = {'ss': response.cookies['ss'].value}
		c.user = authenticate(username='******', password='******')
		c.user = MHLUser.objects.get(id=c.user.id)
		opub = OwnerPublicKey.objects.get_pubkey(owner=c.user)
		msg = encrypt_object(SecureTestMessage, {}, cleartext, opub)
		c.user.set_password('gorilla')
		c.user.save()
		creds = strengthen_key(ADMIN_PASSWORD)
		admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds)
		privs = UserPrivateKey.objects.filter(user=c.user, credtype=CRED_WEBAPP)
		reset_keys(privs, admin_rsa, 'gorilla')
		c.logout()
		response = c.post('/login/', {'username': '******', 'password': '******'})
		c.COOKIES = {'ss': response.cookies['ss'].value}
		decrypted_cleartext = decrypt_object(c, msg)
		self.assertEqual(decrypted_cleartext, cleartext)
		msg.id += 1
		with self.assertRaises(KeyInvalidException):
			decrypt_object(c, msg)
		response = c.logout()
Example #9
0
 def test_static_reset(self):
     # new way will obsolete test_gen_new_keys when rm #2115 in
     cleartext = "We never really grow up, we only learn how to act in public."
     c = self.client
     # after successful login should get re-direct to /
     response = c.post('/login/', {
         'username': '******',
         'password': '******'
     })
     c.COOKIES = {'ss': response.cookies['ss'].value}
     c.user = authenticate(username='******', password='******')
     c.user = MHLUser.objects.get(id=c.user.id)
     opub = OwnerPublicKey.objects.get_pubkey(owner=c.user)
     msg = encrypt_object(SecureTestMessage, {}, cleartext, opub)
     c.user.set_password('gorilla')
     c.user.save()
     creds = strengthen_key(ADMIN_PASSWORD)
     admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds)
     privs = UserPrivateKey.objects.filter(user=c.user,
                                           credtype=CRED_WEBAPP)
     reset_keys(privs, admin_rsa, 'gorilla')
     c.logout()
     response = c.post('/login/', {
         'username': '******',
         'password': '******'
     })
     c.COOKIES = {'ss': response.cookies['ss'].value}
     decrypted_cleartext = decrypt_object(c, msg)
     self.assertEqual(decrypted_cleartext, cleartext)
     msg.id += 1
     with self.assertRaises(KeyInvalidException):
         decrypt_object(c, msg)
     response = c.logout()
Example #10
0
    def handle(self, *args, **options):
        if (len(args) != 1):
            sys.stderr.write("Admin password required.\n")
            self.print_help(sys.argv[1], "")
        else:
            from MHLogin._admin_reset import ADMIN_RESET_ENCD_RSA

            try:
                force = options.pop('force', False)
                logoff = options.pop('logoff', False)

                admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA,
                                       strengthen_key(args[0]))
                migrate_admin_objectkeys(admin_rsa, force)
                # Remove active sessions, users need to log in. During initial migration
                # rsa keys are grandfathered since we do not know users's password.
                # And we don't want specialized code in KMS checking for this single
                # use-case where keys are grandfathered while user logged in.
                if logoff:
                    Session.objects.filter(
                        expire_date__gte=datetime.now()).delete()
                    SmartPhoneAssn.objects.filter(is_active=True).update(
                        is_active=False)
            except ValueError:
                sys.stderr.write("Invalid password.\n")
Example #11
0
 def test_recovery_key_generation(self):
     c = self.client
     recovery = generate_recovery(self.adminguy, None)
     self.assertTrue(recovery != None)  # all keys still g'fathered so true
     response = c.post('/login/', {
         'username': '******',
         'password': '******'
     })
     self.assertEqual(response.status_code, 302)
     # just extra verification we can get user from django auth
     user = authenticate(username='******', password='******')
     # verify we are logged in
     self.assertEqual(c.session['_auth_user_id'], user.id)
     # get admin reset private key
     creds = strengthen_key(ADMIN_PASSWORD)
     admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds)
     recovery = generate_recovery(self.adminguy, admin_rsa)
     self.assertTrue(recovery != None)
     recovery = generate_recovery(self.adminguy, None)
     self.assertTrue(recovery == None)  # not all keys g'fathered now
     # test recovery on regular user
     recovery = generate_recovery(self.provider, admin_rsa)
     self.assertTrue(recovery != None)
     # logout. cleanup
     response = c.logout()
     self.assertTrue('_auth_user_id' not in c.session)
Example #12
0
def create_rsakeypair(user,
                      keytype=RSA_PRIMARY,
                      credtype=CRED_WEBAPP,
                      creds=None):
    """ Create rsa key pair - public and private, grandfathered if no credentials """
    from MHLogin._admin_reset import ADMIN_RESET_PUBLIC_RSA
    # create RSA public and private key instances
    rsa = RSA.generate(2048, os.urandom)
    # encrypt a copy of rsa key with admin reset pubkey
    adminclearkey = os.urandom(32)
    adminpub = import_rsa(ADMIN_RESET_PUBLIC_RSA)
    admincipher = b64encode(PKCS1_OAEP.new(adminpub).encrypt(adminclearkey))
    adminscopy = export_rsa(rsa, adminclearkey)
    # now create pub/priv pair, encrypting with creds (password, pin, etc.)
    opub = OwnerPublicKey.objects.create(
        owner_id=user.id,
        owner_type=ContentType.objects.get_for_model(user),
        adminscopy=adminscopy,
        admincipher=admincipher,
        publickey=export_rsa(rsa.publickey()),
        keytype=keytype)
    upriv = UserPrivateKey.objects.create(
        user=user,
        opub=opub,
        credtype=credtype,
        privatekey=export_rsa(rsa, strengthen_key(creds
                                                  or settings.SECRET_KEY)),
        gfather=False if creds else True)
    return opub, upriv
Example #13
0
	def test_gen_new_keys(self):
		cleartext = "A sql query walks in to a bar, approaches two tables and asks 'may I join you?'"
		c = self.client
		# after successful login should get re-direct to /
		response = c.post('/login/', {'username': '******', 'password': '******'})
		c.COOKIES = {'ss': response.cookies['ss'].value}
		self.assertEqual(response.status_code, 302)
		# just extra verification we can get user from django auth
		c.user = authenticate(username='******', password='******')
		c.user = MHLUser.objects.get(id=c.user.id)
		msg = encrypt_object(SecureTestMessage, {}, cleartext)
		gen_keys_for_users(msg, [c.user], None, c, ivr=True)
		generate_new_user_keys(c.user, 'monkey')
		c.user.set_password('monkey')
		c.user.save()
		# logout. cleanup
		response = c.logout()
		# simulate admin update invalid keys
		creds = strengthen_key(ADMIN_PASSWORD)
		admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds)
		reset_user_invalid_keys(MHLUser.objects.get(id=c.user.id), admin_rsa)
		# login with new password and verify we can decrypt message
		response = c.post('/login/', {'username': '******', 'password': '******'})
		c.COOKIES = {'ss': response.cookies['ss'].value}
		self.assertEqual(response.status_code, 302)
		# just extra verification we can get user from django auth
		c.user = authenticate(username='******', password='******')
		# verify we are logged in
		self.assertEqual(c.session['_auth_user_id'], c.user.id)
		decrypted_cleartext = decrypt_object(c, msg)
		self.assertEqual(decrypted_cleartext, cleartext)
		response = c.logout()
Example #14
0
def admin_decrypt_cipherkey(admin_creds, obj):
	""" ADMIN UTILITY, TODO: move this to black box, rm #2115 """
	clearkey = None
	ct = ContentType.objects.get_for_model(obj)
	encobj = EncryptedObject.objects.filter(object_type=ct, object_id=obj.pk)
	if encobj.exists():
		from MHLogin._admin_reset import ADMIN_RESET_ENCD_RSA
		admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, strengthen_key(admin_creds))
		# get first match since we are decrypting admincipher
		opub = encobj[0].opub
		# decrypt adminscopy rsa key for this encd object
		adminclearkey = PKCS1_OAEP.new(admin_rsa).decrypt(b64decode(opub.admincipher))
		rsa = import_rsa(opub.adminscopy, adminclearkey)
		# finally, decrypt encobj's cipherkey with decrypted admins rsa copy
		clearkey = PKCS1_OAEP.new(rsa).decrypt(b64decode(encobj[0].cipherkey))

	return clearkey
Example #15
0
def reset_keys(uprivs_qry, admin_rsa, creds=None):
	""" For rm #450, static reset user keys.  Obsoletes reset_user_invalid_keys()
		and generate_new_user_keys() when black box in office and rm #2115 done. """
	for priv in uprivs_qry:
		clearkey = PKCS1_OAEP.new(admin_rsa).decrypt(b64decode(priv.opub.admincipher))
		rsa = import_rsa(priv.opub.adminscopy, clearkey)
		priv.privatekey = export_rsa(rsa, strengthen_key(creds or settings.SECRET_KEY))
		priv.gfather = False if creds else True
		priv.save()
Example #16
0
def recrypt_ivr_key_via_web_creds(user, request, new_pin):
	""" decrypt special web enc'd ivr key then recrypt pin enc'd ivr key with new pin """ 
	opub = OwnerPublicKey.objects.get_pubkey(owner=user, keytype=RSA_IVR)
	uprivw = UserPrivateKey.objects.get_privkey(user, opub, CRED_WEBAPP, gfather=False)
	rsa = import_rsa(uprivw.privatekey, get_user_key(request))
	# ivr pin may still be g'fathered
	uprivi = UserPrivateKey.objects.get_privkey(user, opub, CRED_IVRPIN)
	uprivi.privatekey = export_rsa(rsa, strengthen_key(new_pin))
	uprivi.gfather = False
	uprivi.save()
Example #17
0
def admin_decrypt_cipherkey(admin_creds, obj):
    """ ADMIN UTILITY, TODO: move this to black box, rm #2115 """
    clearkey = None
    ct = ContentType.objects.get_for_model(obj)
    encobj = EncryptedObject.objects.filter(object_type=ct, object_id=obj.pk)
    if encobj.exists():
        from MHLogin._admin_reset import ADMIN_RESET_ENCD_RSA
        admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA,
                               strengthen_key(admin_creds))
        # get first match since we are decrypting admincipher
        opub = encobj[0].opub
        # decrypt adminscopy rsa key for this encd object
        adminclearkey = PKCS1_OAEP.new(admin_rsa).decrypt(
            b64decode(opub.admincipher))
        rsa = import_rsa(opub.adminscopy, adminclearkey)
        # finally, decrypt encobj's cipherkey with decrypted admins rsa copy
        clearkey = PKCS1_OAEP.new(rsa).decrypt(b64decode(encobj[0].cipherkey))

    return clearkey
Example #18
0
def reset_keys(uprivs_qry, admin_rsa, creds=None):
    """ For rm #450, static reset user keys.  Obsoletes reset_user_invalid_keys()
		and generate_new_user_keys() when black box in office and rm #2115 done. """
    for priv in uprivs_qry:
        clearkey = PKCS1_OAEP.new(admin_rsa).decrypt(
            b64decode(priv.opub.admincipher))
        rsa = import_rsa(priv.opub.adminscopy, clearkey)
        priv.privatekey = export_rsa(
            rsa, strengthen_key(creds or settings.SECRET_KEY))
        priv.gfather = False if creds else True
        priv.save()
Example #19
0
 def test_login_and_rsa_key_import_export(self):
     c = self.client
     response = c.post('/login/', {
         'username': '******',
         'password': '******'
     })
     self.assertEqual(response.status_code, 302)
     # just extra verification we can get user from django auth
     user = authenticate(username='******', password='******')
     user = MHLUser.objects.get(id=user.id)
     # verify we are logged in
     self.assertEqual(c.session['_auth_user_id'], user.id)
     # These should match:
     self.assertEqual(get_user_key(c, response.cookies['ss'].value),
                      strengthen_key('healme'))
     # query our KeyPair we created in setup
     opub = OwnerPublicKey.objects.get_pubkey(owner=user)
     upriv = UserPrivateKey.objects.get_privkey(user=user, opub=opub)
     devnull.write(unicode(upriv))  # simulate __unicode__
     # grab pubkey from db its in RSA export format but double test import/export
     pub_key_from_db = export_rsa(
         import_rsa(upriv.opub.publickey).publickey())
     # grab our binary user credential
     creds = get_user_key(c, response.cookies['ss'].value)
     # properly import
     rsa_key = import_rsa(upriv.privatekey, creds)
     # verify we can properly create RSA objs by importing
     pub_key_from_key = export_rsa(rsa_key.publickey())
     # verify match
     self.assertEqual(pub_key_from_db, pub_key_from_key)
     # now test decryption of key with admin credentials
     creds = strengthen_key(ADMIN_PASSWORD)
     admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds)
     adminclear = PKCS1_OAEP.new(admin_rsa).decrypt(
         b64decode(upriv.opub.admincipher))
     rsa_key = import_rsa(upriv.opub.adminscopy, adminclear)
     # verify match
     self.assertEqual(pub_key_from_db, export_rsa(rsa_key.publickey()))
     # now logout, we can alternatively call c.post('/logout/')
     response = c.logout()
     self.assertTrue('_auth_user_id' not in c.session)
Example #20
0
 def test_rekey_reset(self):
     cleartext = "Who is the best super hero of all time?"
     c = self.client
     response = c.post('/login/', {
         'username': '******',
         'password': '******'
     })
     self.assertEqual(response.status_code, 302)
     # just extra verification we can get user from django auth
     user = authenticate(username='******', password='******')
     user = MHLUser.objects.get(id=user.id)
     # verify we are logged in
     self.assertEqual(c.session['_auth_user_id'], user.id)
     # get users' public key
     opub = OwnerPublicKey.objects.get_pubkey(owner=user)
     # encrypt_object encrypts w/user pub key
     msg = encrypt_object(SecureTestMessage, {}, cleartext, opub)
     # encrypt_object() creates EncryptedObject
     encobj = EncryptedObject.objects.get_object(msg, opub)
     # test decryption of keys with user's credentials when not grandfathered
     upriv = UserPrivateKey.objects.get(user=user, opub=opub)
     clearkey = encobj.decrypt_cipherkey(upriv, strengthen_key('healme'))
     # now call the object's decrypt method
     decrypted_cleartext = msg.decrypt(c, clearkey)
     # verify they do match after decryption
     self.assertTrue(decrypted_cleartext == cleartext)
     # get admin reset key
     creds = strengthen_key(ADMIN_PASSWORD)
     admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds)
     privs = UserPrivateKey.objects.filter(user=user, credtype=CRED_WEBAPP)
     reset_keys(privs, admin_rsa)
     # fetch the encrypted object again but decrypt with initial settings
     encobj = EncryptedObject.objects.get_object(msg, opub)
     # test decryption with initial credentials when grandfathered
     upriv = UserPrivateKey.objects.get(user=user, opub=opub)
     clearkey = encobj.decrypt_cipherkey(
         upriv, strengthen_key(settings.SECRET_KEY))
     # now call the object's decrypt method
     decrypted_cleartext = msg.decrypt(c, clearkey)
     # verify they do match after decryption
     self.assertTrue(decrypted_cleartext == cleartext)
     # now logout, we can alternatively call c.post('/logout/')
     response = c.logout()
     self.assertTrue('_auth_user_id' not in c.session)
     # try resetting admins keys
     privs = UserPrivateKey.objects.filter(user=self.adminguy,
                                           credtype=CRED_WEBAPP)
     reset_keys(privs, admin_rsa)
     # test str rep of encobj
     self.assertEqual(
         unicode(encobj), u"SecureTestMessage object %s, key type: %s" %
         (user, RSA_TYPES[encobj.opub.keytype]), encobj)
Example #21
0
def recrypt_ivr_key_via_web_creds(user, request, new_pin):
    """ decrypt special web enc'd ivr key then recrypt pin enc'd ivr key with new pin """
    opub = OwnerPublicKey.objects.get_pubkey(owner=user, keytype=RSA_IVR)
    uprivw = UserPrivateKey.objects.get_privkey(user,
                                                opub,
                                                CRED_WEBAPP,
                                                gfather=False)
    rsa = import_rsa(uprivw.privatekey, get_user_key(request))
    # ivr pin may still be g'fathered
    uprivi = UserPrivateKey.objects.get_privkey(user, opub, CRED_IVRPIN)
    uprivi.privatekey = export_rsa(rsa, strengthen_key(new_pin))
    uprivi.gfather = False
    uprivi.save()
Example #22
0
def generate_recovery(user, admin_rsa=None):
	""" Generate recovery key: must provide admin creds or all keys g'fathered """
	recovery_key, recovery = os.urandom(32), None
	if admin_rsa:
		# generate recovery regardless of g'fathered state when given admin_rsa
		for priv in UserPrivateKey.objects.filter(user=user):
			clearkey = PKCS1_OAEP.new(admin_rsa).decrypt(b64decode(priv.opub.admincipher))
			rsa = import_rsa(priv.opub.adminscopy, clearkey)
			priv.recovery = export_rsa(rsa, recovery_key)
			priv.save()
		recovery = b16encode(recovery_key)
	elif not UserPrivateKey.objects.filter(user=user, gfather=False).exists():
		# no admin (e.g. user signup) but all keys must be g'fathered
		initial_creds = strengthen_key(settings.SECRET_KEY)
		for priv in UserPrivateKey.objects.filter(user=user):
			rsa = import_rsa(priv.privatekey, initial_creds)
			priv.recovery = export_rsa(rsa, recovery_key)
			priv.save()
		recovery = b16encode(recovery_key)
	if not recovery:
		logger.critical("Recovery key not created for user: %s" % user)

	return recovery  # send to user, don't store anywhere
Example #23
0
def recrypt_keys(uprivs_qry, old_creds, new_creds, strengthd=False):
	""" Recrypt keys when user changes password/pin or un-grandfathered.

	:param strengthd: Handle annoying corner case, IVR does not ask for old
		pin when user wants to change pin via IVR, we have only userkey, i.e.
		strengthen_key(pin). TODO: Redmine so behavior is same as web/app.
	:raises: ValueError if old_creds incorrect
	"""
	old_creds = old_creds if strengthd else strengthen_key(old_creds)
	new_creds = new_creds if strengthd else strengthen_key(new_creds)
	for priv in uprivs_qry:
		rsa = import_rsa(priv.privatekey, old_creds)
		priv.privatekey = export_rsa(rsa, new_creds)
		priv.gfather = False
		priv.save()
Example #24
0
def recrypt_keys(uprivs_qry, old_creds, new_creds, strengthd=False):
    """ Recrypt keys when user changes password/pin or un-grandfathered.

	:param strengthd: Handle annoying corner case, IVR does not ask for old
		pin when user wants to change pin via IVR, we have only userkey, i.e.
		strengthen_key(pin). TODO: Redmine so behavior is same as web/app.
	:raises: ValueError if old_creds incorrect
	"""
    old_creds = old_creds if strengthd else strengthen_key(old_creds)
    new_creds = new_creds if strengthd else strengthen_key(new_creds)
    for priv in uprivs_qry:
        rsa = import_rsa(priv.privatekey, old_creds)
        priv.privatekey = export_rsa(rsa, new_creds)
        priv.gfather = False
        priv.save()
Example #25
0
def generate_recovery(user, admin_rsa=None):
    """ Generate recovery key: must provide admin creds or all keys g'fathered """
    recovery_key, recovery = os.urandom(32), None
    if admin_rsa:
        # generate recovery regardless of g'fathered state when given admin_rsa
        for priv in UserPrivateKey.objects.filter(user=user):
            clearkey = PKCS1_OAEP.new(admin_rsa).decrypt(
                b64decode(priv.opub.admincipher))
            rsa = import_rsa(priv.opub.adminscopy, clearkey)
            priv.recovery = export_rsa(rsa, recovery_key)
            priv.save()
        recovery = b16encode(recovery_key)
    elif not UserPrivateKey.objects.filter(user=user, gfather=False).exists():
        # no admin (e.g. user signup) but all keys must be g'fathered
        initial_creds = strengthen_key(settings.SECRET_KEY)
        for priv in UserPrivateKey.objects.filter(user=user):
            rsa = import_rsa(priv.privatekey, initial_creds)
            priv.recovery = export_rsa(rsa, recovery_key)
            priv.save()
        recovery = b16encode(recovery_key)
    if not recovery:
        logger.critical("Recovery key not created for user: %s" % user)

    return recovery  # send to user, don't store anywhere
Example #26
0
def create_default_keys(user, webcreds=None, ivrcreds=None):
	""" Helper to create standard user setup:
			1. Web/App RSA key encrypted w/web credentials (password)
			2. IVR RSA key encrypted w/ivr credentials (pin)
			3. Same IVR RSA key encrypted w/web credentials
	"""
	# 1. Web/App RSA key encrypted w/web credentials
	create_rsakeypair(user, RSA_PRIMARY, CRED_WEBAPP, webcreds)
	# 2. IVR RSA key encrypted w/IVR PIN credentials
	ipub, ipriv = create_rsakeypair(user, RSA_IVR, CRED_IVRPIN, ivrcreds)
	# 3. Same IVR key, this is so users can change a forgotten pin via web
	rsa = import_rsa(ipriv.privatekey, strengthen_key(ivrcreds or settings.SECRET_KEY))
	UserPrivateKey.objects.create(user=user, opub=ipub, credtype=CRED_WEBAPP,
		privatekey=export_rsa(rsa, strengthen_key(webcreds or settings.SECRET_KEY)),
			gfather=False if webcreds else True)
Example #27
0
	def test_login_and_rsa_key_import_export(self):
		c = self.client
		response = c.post('/login/', {'username': '******', 'password': '******'})
		self.assertEqual(response.status_code, 302)
		# just extra verification we can get user from django auth
		user = authenticate(username='******', password='******')
		user = MHLUser.objects.get(id=user.id)
		# verify we are logged in
		self.assertEqual(c.session['_auth_user_id'], user.id)
		# These should match:
		self.assertEqual(get_user_key(c, response.cookies['ss'].value),
				strengthen_key('healme'))
		# query our KeyPair we created in setup
		opub = OwnerPublicKey.objects.get_pubkey(owner=user)
		upriv = UserPrivateKey.objects.get_privkey(user=user, opub=opub)
		devnull.write(unicode(upriv))  # simulate __unicode__
		# grab pubkey from db its in RSA export format but double test import/export
		pub_key_from_db = export_rsa(import_rsa(upriv.opub.publickey).publickey())
		# grab our binary user credential
		creds = get_user_key(c, response.cookies['ss'].value)
		# properly import
		rsa_key = import_rsa(upriv.privatekey, creds)
		# verify we can properly create RSA objs by importing
		pub_key_from_key = export_rsa(rsa_key.publickey())
		# verify match
		self.assertEqual(pub_key_from_db, pub_key_from_key)
		# now test decryption of key with admin credentials
		creds = strengthen_key(ADMIN_PASSWORD)
		admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds)
		adminclear = PKCS1_OAEP.new(admin_rsa).decrypt(b64decode(upriv.opub.admincipher))
		rsa_key = import_rsa(upriv.opub.adminscopy, adminclear)
		# verify match
		self.assertEqual(pub_key_from_db, export_rsa(rsa_key.publickey()))
		# now logout, we can alternatively call c.post('/logout/')
		response = c.logout()
		self.assertTrue('_auth_user_id' not in c.session)
Example #28
0
	def test_rekey_reset(self):
		cleartext = "Who is the best super hero of all time?"
		c = self.client
		response = c.post('/login/', {'username': '******', 'password': '******'})
		self.assertEqual(response.status_code, 302)
		# just extra verification we can get user from django auth
		user = authenticate(username='******', password='******')
		user = MHLUser.objects.get(id=user.id)
		# verify we are logged in
		self.assertEqual(c.session['_auth_user_id'], user.id)
		# get users' public key
		opub = OwnerPublicKey.objects.get_pubkey(owner=user)
		# encrypt_object encrypts w/user pub key
		msg = encrypt_object(SecureTestMessage, {}, cleartext, opub)
		# encrypt_object() creates EncryptedObject
		encobj = EncryptedObject.objects.get_object(msg, opub)
		# test decryption of keys with user's credentials when not grandfathered
		upriv = UserPrivateKey.objects.get(user=user, opub=opub)
		clearkey = encobj.decrypt_cipherkey(upriv, strengthen_key('healme'))
		# now call the object's decrypt method
		decrypted_cleartext = msg.decrypt(c, clearkey)
		# verify they do match after decryption
		self.assertTrue(decrypted_cleartext == cleartext)
		# get admin reset key
		creds = strengthen_key(ADMIN_PASSWORD)
		admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds)
		privs = UserPrivateKey.objects.filter(user=user, credtype=CRED_WEBAPP)
		reset_keys(privs, admin_rsa)
		# fetch the encrypted object again but decrypt with initial settings
		encobj = EncryptedObject.objects.get_object(msg, opub)
		# test decryption with initial credentials when grandfathered
		upriv = UserPrivateKey.objects.get(user=user, opub=opub)
		clearkey = encobj.decrypt_cipherkey(upriv, strengthen_key(settings.SECRET_KEY))
		# now call the object's decrypt method
		decrypted_cleartext = msg.decrypt(c, clearkey)
		# verify they do match after decryption
		self.assertTrue(decrypted_cleartext == cleartext)
		# now logout, we can alternatively call c.post('/logout/')
		response = c.logout()
		self.assertTrue('_auth_user_id' not in c.session)
		# try resetting admins keys
		privs = UserPrivateKey.objects.filter(user=self.adminguy, credtype=CRED_WEBAPP)
		reset_keys(privs, admin_rsa)
		# test str rep of encobj
		self.assertEqual(unicode(encobj), u"SecureTestMessage object %s, key type: %s"
			% (user, RSA_TYPES[encobj.opub.keytype]), encobj)
Example #29
0
def create_rsakeypair(user, keytype=RSA_PRIMARY, credtype=CRED_WEBAPP, creds=None):
	""" Create rsa key pair - public and private, grandfathered if no credentials """
	from MHLogin._admin_reset import ADMIN_RESET_PUBLIC_RSA
	# create RSA public and private key instances
	rsa = RSA.generate(2048, os.urandom)
	# encrypt a copy of rsa key with admin reset pubkey
	adminclearkey = os.urandom(32)
	adminpub = import_rsa(ADMIN_RESET_PUBLIC_RSA)
	admincipher = b64encode(PKCS1_OAEP.new(adminpub).encrypt(adminclearkey))
	adminscopy = export_rsa(rsa, adminclearkey)
	# now create pub/priv pair, encrypting with creds (password, pin, etc.)
	opub = OwnerPublicKey.objects.create(owner_id=user.id,
		owner_type=ContentType.objects.get_for_model(user), adminscopy=adminscopy,
			admincipher=admincipher, publickey=export_rsa(rsa.publickey()), keytype=keytype)
	upriv = UserPrivateKey.objects.create(user=user, opub=opub, credtype=credtype,
		privatekey=export_rsa(rsa, strengthen_key(creds or settings.SECRET_KEY)), 
			gfather=False if creds else True)
	return opub, upriv
Example #30
0
def create_default_keys(user, webcreds=None, ivrcreds=None):
    """ Helper to create standard user setup:
			1. Web/App RSA key encrypted w/web credentials (password)
			2. IVR RSA key encrypted w/ivr credentials (pin)
			3. Same IVR RSA key encrypted w/web credentials
	"""
    # 1. Web/App RSA key encrypted w/web credentials
    create_rsakeypair(user, RSA_PRIMARY, CRED_WEBAPP, webcreds)
    # 2. IVR RSA key encrypted w/IVR PIN credentials
    ipub, ipriv = create_rsakeypair(user, RSA_IVR, CRED_IVRPIN, ivrcreds)
    # 3. Same IVR key, this is so users can change a forgotten pin via web
    rsa = import_rsa(ipriv.privatekey,
                     strengthen_key(ivrcreds or settings.SECRET_KEY))
    UserPrivateKey.objects.create(user=user,
                                  opub=ipub,
                                  credtype=CRED_WEBAPP,
                                  privatekey=export_rsa(
                                      rsa,
                                      strengthen_key(webcreds
                                                     or settings.SECRET_KEY)),
                                  gfather=False if webcreds else True)
Example #31
0
def reset_private_keys(request):
    """
	This view takes the KMS administrator password, and for each user whose
	password was reset, generates new private keys.

	:param request: The HTTP request
	:type request: django.core.handlers.wsgi.WSGIRequest  
	:returns: django.http.HttpResponse -- The webpage 
	"""
    context, resp = get_context(request), None
    log_qs = PasswordResetLog.objects.filter(reset=True,
                                             resolved=False).values('user')
    reset_users = context['reset_users'] = MHLUser.objects.filter(
        pk__in=log_qs)

    if request.method == 'POST':
        form = context['form'] = PasswordForm(request.POST)
        if form.is_valid():
            try:
                from MHLogin._admin_reset import ADMIN_RESET_ENCD_RSA
                creds = strengthen_key(form.cleaned_data['password'])
                admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds)
            except ValueError:
                msg = _('Invalid password for admin reset key.')
                form._errors['password'] = form.error_class([msg])
            else:
                for user in reset_users:
                    reset_user_invalid_keys(user, admin_rsa)
                    PasswordResetLog.objects.filter(
                        reset=True, resolved=False, user=user).update(
                            resolved=True,
                            servicer=request.user,
                            servicer_ip=request.META['REMOTE_ADDR'],
                            resolution_timestamp=datetime.datetime.now())
                resp = render_to_response('PrivateKeyResetComplete.html',
                                          context)
    else:
        context['form'] = PasswordForm()

    return resp or render_to_response('PrivateKeyReset.html', context)
Example #32
0
	def handle(self, *args, **options):
		if (len(args) != 1):
			sys.stderr.write("Admin password required.\n")
			self.print_help(sys.argv[1], "")
		else:
			from MHLogin._admin_reset import ADMIN_RESET_ENCD_RSA

			try:
				force = options.pop('force', False)
				logoff = options.pop('logoff', False)

				admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, strengthen_key(args[0]))
				migrate_admin_objectkeys(admin_rsa, force)
				# Remove active sessions, users need to log in. During initial migration
				# rsa keys are grandfathered since we do not know users's password.
				# And we don't want specialized code in KMS checking for this single
				# use-case where keys are grandfathered while user logged in.
				if logoff:
					Session.objects.filter(expire_date__gte=datetime.now()).delete()
					SmartPhoneAssn.objects.filter(is_active=True).update(is_active=False)
			except ValueError:
				sys.stderr.write("Invalid password.\n")
Example #33
0
 def test_gen_new_keys(self):
     cleartext = "A sql query walks in to a bar, approaches two tables and asks 'may I join you?'"
     c = self.client
     # after successful login should get re-direct to /
     response = c.post('/login/', {
         'username': '******',
         'password': '******'
     })
     c.COOKIES = {'ss': response.cookies['ss'].value}
     self.assertEqual(response.status_code, 302)
     # just extra verification we can get user from django auth
     c.user = authenticate(username='******', password='******')
     c.user = MHLUser.objects.get(id=c.user.id)
     msg = encrypt_object(SecureTestMessage, {}, cleartext)
     gen_keys_for_users(msg, [c.user], None, c, ivr=True)
     generate_new_user_keys(c.user, 'monkey')
     c.user.set_password('monkey')
     c.user.save()
     # logout. cleanup
     response = c.logout()
     # simulate admin update invalid keys
     creds = strengthen_key(ADMIN_PASSWORD)
     admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds)
     reset_user_invalid_keys(MHLUser.objects.get(id=c.user.id), admin_rsa)
     # login with new password and verify we can decrypt message
     response = c.post('/login/', {
         'username': '******',
         'password': '******'
     })
     c.COOKIES = {'ss': response.cookies['ss'].value}
     self.assertEqual(response.status_code, 302)
     # just extra verification we can get user from django auth
     c.user = authenticate(username='******', password='******')
     # verify we are logged in
     self.assertEqual(c.session['_auth_user_id'], c.user.id)
     decrypted_cleartext = decrypt_object(c, msg)
     self.assertEqual(decrypted_cleartext, cleartext)
     response = c.logout()
Example #34
0
	def test_recovery_key_generation(self):
		c = self.client
		recovery = generate_recovery(self.adminguy, None)
		self.assertTrue(recovery != None)  # all keys still g'fathered so true
		response = c.post('/login/', {'username': '******', 'password': '******'})
		self.assertEqual(response.status_code, 302)
		# just extra verification we can get user from django auth
		user = authenticate(username='******', password='******')
		# verify we are logged in
		self.assertEqual(c.session['_auth_user_id'], user.id)
		# get admin reset private key
		creds = strengthen_key(ADMIN_PASSWORD)
		admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds)
		recovery = generate_recovery(self.adminguy, admin_rsa)
		self.assertTrue(recovery != None)
		recovery = generate_recovery(self.adminguy, None)
		self.assertTrue(recovery == None)  # not all keys g'fathered now
		# test recovery on regular user
		recovery = generate_recovery(self.provider, admin_rsa)
		self.assertTrue(recovery != None)
		# logout. cleanup
		response = c.logout()
		self.assertTrue('_auth_user_id' not in c.session)