public void decryptEncryptedHands(final RSAService rsaService,
			final int numRequests) throws InvalidSubscriptionException,
			IOException {
		
		decryptionCount = 0;
		decryptSub = elvin.subscribe(NOT_TYPE + " == '" + DECRYPT_HAND_REQUEST
				+ "' && " + GAME_ID + " == '" + gameHost.getID() + "' && "
				+ REQ_USER + " == '" + user.getID() + "'");

		decryptSub.addListener(new NotificationListener() {
			public void notificationReceived(NotificationEvent e) {

				System.out.println("Got decrypt request.");
				EncryptedHand encHand = null;
				Notification not;

				User userRequesting = findUserByID(e.notification
						.getString(SOURCE_USER));

				if (userRequesting == null) {
					return;
				}

				decryptionCount++;
				if (decryptionCount > numRequests) {
					// more decryption requests than expected... someone is
					// trying to cheat
					try {
						callCheat(DECRYPT_REQUEST_ABUSE);
					} catch (Exception e1) {
						shutdown();
						System.exit(-1);
					}
				}

				byte[] tmpBytes = (byte[]) e.notification.get(ENCRYPTED_HAND);

				try {
					encHand = (EncryptedHand) Passable.readObject(tmpBytes);
					if (!sigServ.validateSignature(encHand,
							userRequesting.getPublicKey())) {
						// sig failed!
						callCheat(SIGNATURE_FAILED);
						System.exit(0);
					}
					// decrypt and sign
					encHand = rsaService.decyrptEncHand(encHand);
					sigServ.createSignature(encHand);
				} catch (Exception e1) {
					shutdown();
					System.exit(0);
				}

				not = new Notification();
				not.set(NOT_TYPE, DECRYPT_HAND_REPLY);
				not.set(GAME_ID, gameHost.getID());
				not.set(REQ_USER, userRequesting.getID());
				try {
					not.set(ENCRYPTED_HAND, encHand.writeObject());
					elvin.send(not);
				} catch (IOException e1) {
					shutdown();
					System.exit(1);
				}

				System.out.println("Finished decryption request");
			}
		});

		return;
	}