views:

254

answers:

5

Dear all,

I am working on a project in which I have to develop bio-passwords based on user's keystroke style. Suppose a user types a password for 20 times, his keystrokes are recorded, like

holdtime : time for which a particular key is pressed. digraph time : time it takes to press a different key.

suppose a user types a password " COMPUTER". I need to know the time for which every key is pressed. something like :

holdtime for the above password is

C-- 200ms O-- 130ms M-- 150ms P-- 175ms U-- 320ms T-- 230ms E-- 120ms R-- 300ms

The rational behind this is , every user will have a different holdtime. Say a old person is typing the password, he will take more time then a student. And it will be unique to a particular person. To do this project, I need to record the time for each key pressed. I would greatly appreciate if anyone can guide me in how to get these times.

Editing from here.. Language is not important, but I would prefer it in C. I am more interested in getting the dataset.

+6  A: 

Record the KeyDown and KeyUp events, and do a diff on the timestamps of each.

http://code.activestate.com/recipes/203830/

Edit: You may want to check out wxPython, it should help you out:

http://www.wxpython.org/onlinedocs.php

in particular:

http://docs.wxwidgets.org/stable/wx_wxkeyevent.html#wxkeyevent

jvenema
thanks for the link. I would check it and get back to u.
Adi
Hi, I tried running the code, but i did not understand how it works, it gives some numbers on the terminal which goes in an infinite loop. i would appreciate if you can give some further guidance.
Adi
A: 

If you read from the terminal in conical mode, you can read each keystroke as it's pressed. You won't see keydown keyup events, like you could if you trapped X events, but it's probably easier, especially if you're just running in a console or terminal.

John Gordon
A: 

The answer is conditionally "yes".

If your languages/environment has interactive keyboard support that offers Key-Down and Key-Up events, then you catch both events and time the difference between them.

This would be trivially easy in JavaScript on a web page, which would also be the easiest way to show off your work to a wider audience.

dkamins
Thanks Dkamins,I really appreciate your comment. I would like to know how can I do it in Javascript . Can u offer me some links to start.
Adi
+2  A: 

Have a look at ncurses. It is a terrific tool for getting information about keypresses in the terminal.

Have a look at this link too.

George Edison
thanks George for the response. I see that I can use Ncurses to know the keys pressed ,can i also use it to know the keyup and keydown times and take a difference to get the hold key time ?
Adi
Well what you can do is to get the system time when the key is pushed down and the system time when the key is released. Then subtract the difference to get the hold time for the key.
George Edison
ohk u mean, i can use gettimeofday or something to note down the time and then subtract it.. thanks for the hint, i will try it and get back to u..
Adi
+3  A: 

You mentioned you'd prefer it in C, but since you tagged it Python... :)

Also, since you say you're looking for building a dataset, I assume you'll have to invite users to type in arbitrary text, so you'll need some sort of interface (graphical or otherwise).

Here's a quick example using pygame. You can trivially modify it to ask users to type specific words, but, as it is, it'll just let the user type in arbitrary text, record pressing times for all keypresses, and print each hold and digraph times, in the order that the user typed it, when it exits (i.e., when the user presses Esc).

As Kibibu noticed, showing the user what he's typing in realtime introduces a delay which might mask real key-pressing times, so this code only displays what the user has typed when he types "Enter".

Update: it now calculates digraph as well as hold times (excluding Enter in both cases).

Update2: Per Adi's request, changed from displaying average to displaying each individual time, in order.

import sys
from collections import defaultdict
from time import time
import pygame
from pygame.key import name as keyname
from pygame.locals import *

# Mapping of a key to a list of holdtimes (from which you can average, etc)
holdtimes = defaultdict(list)
# Mapping of a key pair to a list of digraph times
digraphs = defaultdict(list)
# Keys which have been pressed down, but not up yet.
pending = {}
# Last key to be de-pressed, corresponding time).
last_key = None
# Text that the user has typed so far (one sublist for every Enter pressed)
typed_text = [[]]

def show_times():
    all_text = [k for line in typed_text for k in line]
    print "Holdtimes:"
    for key in all_text:
        print "%s: %.5f" % (key, holdtimes[key].pop(0))

    print "Digraphs:"
    for key1, key2 in zip(all_text, all_text[1:]):
        print "(%s, %s): %.5f" % (key1, key2,
                                  digraphs[(key1, key2)].pop(0))

def time_keypresses(events):
    global last_key
    for event in events:
        if event.type == KEYDOWN:
            # ESC exits the program
            if event.key == K_ESCAPE:
                show_times()
                sys.exit(0)

            t = pending[event.key] = time()
            if last_key is not None:
                if event.key != K_RETURN:
                    digraphs[(last_key[0], keyname(event.key))].append(t - last_key[1])
                last_key = None
        elif event.type == KEYUP:
            if event.key == K_RETURN:
                update_screen()
                typed_text.append([])
                pending.pop(event.key)
                last_key = None
            else:
                t = time()
                holdtimes[keyname(event.key)].append(t - pending.pop(event.key))
                last_key = [keyname(event.key), t]
                typed_text[-1].append(keyname(event.key))
        # Any other event handling you might have would go here...

def update_screen():
    global screen
    screen.fill((255, 255, 255))

    header_font = pygame.font.Font(None, 42)
    header = header_font.render("Type away! Press 'Enter' to show.", True, (0, 0, 0))
    header_rect = header.get_rect()
    header_rect.centerx = screen.get_rect().centerx
    header_rect.centery = screen.get_rect().centery - 100

    text_font = pygame.font.Font(None, 32)
    user_text = text_font.render("".join(typed_text[-1]) if typed_text[-1] else "...",
                                 True, (0, 0, 255))
    text_rect = user_text.get_rect()
    text_rect.centerx = screen.get_rect().centerx
    text_rect.centery = screen.get_rect().centery    

    screen.blit(header, header_rect)
    screen.blit(user_text, text_rect)

    pygame.display.update()


if __name__ == '__main__':
    pygame.init()
    window = pygame.display.set_mode((800, 600))
    screen = pygame.display.get_surface()
    update_screen()
    while True:
        time_keypresses(pygame.event.get())
rbp
Oops, sorry, I accidentally posted this twice. I'm deleting the wrong entry.
rbp
What sort of time resolution does this yield? I'd suggest decoupling the screen update from the event loop so all that blitting doesn't reduce your timer accuracy (something as trivial as this screen update probably runs at 10000 hz anyway, but still...)
kibibu
are you sure you posted the whole code, i think some parts are missing
berkay
Kibibu: Yeah, it'd occurred to me after I posted my original answer. I've updated the script to only show what the user last typed at each time he presses Enter. This should avoid the screen update delay, at the expense of the user not seeing what he types in realtime.
rbp
Berkay: I'm pretty sure, I copied directly from Emacs. I've just updated the code, please check again and let me know if you're still having problems running this.
rbp
hi rbp,Thanks for posting the code. I really appreciate it. The code gives me the hold time but does not give me digraph time. Digraph time : Time elapsed if we switch between 2 keys . Say if i first press A and then B . what is the time difference between A and B. Can you give some insight in that.Thanks..in anticipation.
Adi
Ah, yes, I forgot to comment on that: I hadn't really understood what "digraph" meant ;) Is it supposed to be timed by specific key-pairs? Should it time between subsequent pressings of the same key ("a" "a")?
rbp
rbp:you are right sorry about it, for your answer+1.I missed to import pygame and curious about how to measure digraph time? assume D and E pressed sequentially, it should be (keydowntime for E-keyuptime for D) can i do that with that code?
berkay
Hi rbp,As Digraph time is basically time between two keys. Say A is pressed then now u press B, so what is the time between 2 keys. If you press same keys twice, say A and A. Then wht is time between the two. I hope this makes it clear.
Adi
I see. It's only a very short leap from the holdtimes handling code. Please take a look at the updated version. I've also corrected a small bug, wherein the average holdtime was being shown incorrectly :)
rbp
Thanks.. I will see and get back to you. Thanks a lot once again for the guidance..
Adi
Hi Rbp,I have been using the code for my application and works fine. Since, I never used python ,my questions may be trivial also. But I have one concern, whenever I type in same characters, say I type in "nahan".. It gives following output :Holdtimes:a: 0.08803h: 0.09536n: 0.09694Digraphs:(a, h): 0.11334(a, n): 0.07949(h, a): 0.06377(n, a): 0.04700This is our current output, In next comment please see what exactly will help us create the dataset.
Adi
So for same characters 'n' and 'a', It gives avg times for these and for digraph times, it gives some random order. -It will be really nice if we can get something like following:Expected output.. x denotes some time..Holdtimes:n: 0.08803a: xxxxxh:xxxxa:xxxxn:xxxxxdigraph times:(n,a) : xxxx(a,h) : xxxx(h,a) : xxxx(a,n) : xxxxIt will help us to create a good data set and then we can create bio-passwords based on users profile. I hope you understand my concern and would look forward to hear from you.Thanks
Adi
by same character 'n' and 'a' I mean, if they repeat in a string, so in nahan there are 2 n's and 2 a's. So for these it gives avg and not exact, i want exact for each ..
Adi
The output is not in a random order, it's lexically ordered (that's what "sorted(holdtimes.iteritems())" does, in the loop inside the "show_times" function).It's fairly trivial to sort the output to match the input order, but you need to make several small decisions about it. For instance, what to do when the user repeats a keystroke, or a key sequence; currently, the code prints the average time (for both holdtimes and digraph times), but that doesn't make sense if you choose to print each keystroke individually (continues...)
rbp
If you intend to use this code "in real life", I think you should familiarise yourself a bit with Python (which I used because your question was tagged "python", so I assumed you had some knowledge of it). It's not hard at all, there's a very nice (though a bit outdated) guide at http://diveintopython.org/toc/index.html and the official tutorial is also very good: http://docs.python.org/tutorial/index.html . Otherwise, you'll need me to make every little change for you, which is not feasible. (continues...)
rbp
This particular change is trivial: append every keystroke to a list (similar to the "typed_text" variable, but don't clear it on Enter), and, in the show_times() function, iterate over this list and, for every character, pop(0) from the list of recorded times (holdtimes[that_key]). Same for digraphs: for each character, get the next one as well, and pop(0) from digraphs[that_pair].The code I posted times keystrokes and digraphs as you asked, but you'll absolutely need to know *some* Python in order to use it productively, otherwise you're better off hiring someone to deal with such details.
rbp
Hi rbp,I am sorry for bothering you for small trivial things, but I will definitely learn python now and I really appreciate the links which you gave me which will provide a head start for me. Thanks so much for the help.
Adi
Cool, I hope you do! It's a great language :) I've updated the code to fit your needs, I hope you can work from there :)
rbp
Thanks rbp.. You are great..You have motivated me to learn python.. I am comfortable in C , now i will learn python also..
Adi