Category Archives: Tutorials

Passwords: How Websites Do it Wrong, Triaging Services and Memorizing

I was just reading LifeHacker and ran into an old article they linked on “How I’d Hack Your Weak Passwords” by John P. It got me thinking that it’s high time I write up some thoughts of mine on the topic.

Website Passwords

If a website ever sends you an email with your password in it, they are doing something very, very wrong. Actually, they might be doing more than one thing wrong–but I’m just going to focus on the biggest issue:

The fact that the website/company has the ability to show your password to you in any form means one of two things (either are very bad):

  1. Your password is being stored unencrypted, in plaintext, in the database.
  2. Your password is being stored encrypted in the database but can be unencrypted (back into what you type in your keyboard) using a key that is stored somewhere in the website code.

Obviously, the first case is worse–but I’ve seen it in small startup companies.

In either case, anyone with access to the database (and, for #2, the codebase) will have the ability to see your email address, username, password and any other information you’ve given the website. Generally, with web startup companies, this means anyone who works at the company–at the very least it means that the development team has access to it.

This is really bad for you if you use the same password for all websites–especially if you use this password for your email account, which is part of the plain data available. If you are this kind of person and you sign up for a site that treats passwords like this, a malicious (or curious) worker or data thief can simple see your current username,email,password combination, then go to Facebook, Twitter, or any other service they think you use and try those same credentials.

Website Triage

When creating accounts on the web, which is something I do quite a bit, I triage sites like so:

Email

Your email account is the primary gateway to almost all of your other online accounts. If you lose your password (or claim to have lost it), most sites will send instructions to your email account with a simple way to reset your password–often times without needing to supply any other information.
Thus, your email account needs to be hyper secure:

  1. Always use https:// when checking webmail and always use SSL to connect to your email server from clients like Thunderbird, Outlook or Apple Mail.
  2. Make a really strong password for your email account–and make it totally unique! Do not use this password for anything else!

Personally Identifyable + Financial

This includes Facebook, Twitter, Banks, Credit cards, Investment sites, Amazon, LinkedIn… basically, anything that either identifies you to your social groups, work, etc or has the ability to cost you money if compromised.

These accounts need to be extra secure. Unfortunately banks and credit card companies tend to restrict the security of passwords for no good reason. However, luckily, they employ other authentication mechanisms for login and password retrieval.

Now you might think, “What? You treat Facebook with the same password security requirement as your bank?” But I assure you, that doesn’t mean I let my bank password slip, it means I keep my Facebook password strong. It’s bad for someone to compromise your finances but it can also be a nightmare to have someone impersonate and damage your identity.

Everything Else

These would be sites that would only have my email, username and a password but no more personal information–generally services that mean very little to me and would be very easy for someone to forge on my behalf anyway (so I’m not concerned about someone getting in–or of a password leak from another low level site exposing access to this site). An example might be creating an account for a forum or a gaming site, where you need to login to get some info or post a comment. These are throw away accounts that all share the same login information.

Creating Strong Passwords

Gibson Research has an online password generator, along with information regarding the purpose and use:
https://www.grc.com/passwords.htm

After generating passwords of this size, which are generally absurd to imagine memorizing, you can store them in a password keychain. There are many desktop and mobile applications available for this. However, I’ve always been weary of using these programs because essentially, you are putting all of your passwords in a single location, protected by one single password, which is usually weaker than the passwords you can’t be bothered to memorize.

How to Remember a Unique Password for Every Service

If you don’t trust storing all of your passwords in a password keychain tool and you also have trouble remembering passwords, there’s another way.

Consider this simple algorithm for creating decent passwords, which involves only memorizing a single string that you can reuse for generating all of your passwords:

  1. Generate a random character string (6-8 characters is good enough)
  2. Take some portion of the name of the service
  3. Combine

Example:

  1. e$L9wa
  2. Facebook.com – taking ‘book’ (but you could take Face, face, Book, b00k, B00k, cebo, etc)
  3. Password possibilities:
    • e$L9wabook – one after the other
    • booke$L9wa – same as above but reversed
    • eb$oLo9kwa – the every other letter method (a little more difficult for a password thief to realize what your password might be for other services)

Now, when you go to Facebook.com, you can remember your generic random string, look at the name “Facebook” and think about what part of the name you would have used, then try the combination tactic that you think you probably used to create your password. If one doesn’t work, try another. Generally, you will find that it is incredibly easy to recall your password with ease–and after a few times of doing it, you will have effortlessly “memorized” your unique password.

NOTE: if you use an algorithm like this, you run the risk that if someone gets one of your passwords, they can infer a password for another service.

and using numbers and special characters to replace parts of the service name, which will make it much more difficult from a brute force perspective. Even so, this is way better than using the same exact password for every service, which would automatically allow an attacker to steal all of your online accounts. But there are ways to mitigate the risk of one password leak exposing your other accounts.

For more security:

  1. Generate a longer random string
  2. Change that random string regularly (once a week, once a month, your call–but more often is more secure, up to a point)
  3. Choosing odd parts of the service name (rather than “Face” or “Book”, choose “cebo” from the middle to make your algorithm less obvious to someone who captures one of your passwords)
  4. Come up with different rules for each service for integrating the name with your memorized string

follow on Twitter

Dynamic Filterable Life Plan / Timeline (PHP, jQuery, CSS)

I just created my life plan (or the start of one anyway–I’ll be editing this thing for a while) and I figured I’d share with you the code used to make it.
My live updated version is on my Portfolio: The Future as I See It.

Demo


$maxYear){
$diffYears = $year – $maxYear;
$year = $maxYear; // this is what we will use in mktime() then we can add seconds to that output
$addtime = $diffYears * 31536000; // years of seconds
}

// count leap years
$numYears = $year – date(‘Y’);
$leaps = floor($numYears/4);
$addtime -= $leaps * 86400; // subtract these excess days (to get accurate year count)

$date = mktime(0,0,0,$month,$day,$year) + $addtime;
$now = time();
$days = ceil(($date – $now)/86400);
if($days < 365){ return 'in '.$days .' day'.($days==1?'':'s'); }else{ $years = floor($days/365); $days = $days%365; return 'in '.$years.' year'.($years==1?'':'s').', '.$days.' day'.($days==1?'':'s'); } } $events = array( array( 'yyyy'=>‘2010’,’mm’=>’01’,’dd’=>’20’,
‘name’=>’Move to Magdeburg, Deutschland’,
‘info’=>’My family will be moving to Magdeburg to experience living in Germany and to strenghten our deutsche Sprachfähigkeiten.’,
‘type’=>’travel’
),
array(
‘yyyy’=>’2010′,’mm’=>’06’,’dd’=>’15’,
‘name’=>’Produce an iPhone App’,
‘info’=>’This might get done before I move to Magdeburg but this is my personal deadline for a v1.0 release.’,
‘type’=>’work’
),
array(
‘yyyy’=>’2011′,’mm’=>’01’,’dd’=>’20’,
‘name’=>’Move Back to Seattle, WA USA’,
‘info’=>’Unless we decide to stay in Germany or move elsewhere’,
‘type’=>’travel’
),
array(
‘yyyy’=>’2013′,’mm’=>’07’,’dd’=>’15’,
‘name’=>’Accomplish a Free-Standing Backflip’,
‘info’=>’I\’ve done it on a trampoline and with spotters but never alone without aid. This is a life-long goal.’,
‘type’=>’fitness’
),
array(
‘yyyy’=>’2017′,’mm’=>’09’,’dd’=>’01’,
‘name’=>’Publish First Novel’,
‘info’=>’Contact me if you want to be one of my pre-publication reviewers’,
‘type’=>’creative’
),
array(
‘yyyy’=>’2021′,’mm’=>’07’,’dd’=>’22’,
‘name’=>’Give First TED Talk’,
‘info’=>’On what topic? Web, security, social media, nano-technology, engineering, the future, productivity in an age of overabundance? I\’m not sure yet–but it will be awesome.’,
‘url’=>’http://ted.com’,
‘type’=>’social’
),
array(
‘yyyy’=>’2026′,’mm’=>’07’,’dd’=>’22’,
‘name’=>’Engineering Degree from MIT’,
‘info’=>’Oh, yes, I will be going back to school. Probably many times in my life.’,
‘type’=>’education’
),
array(
‘yyyy’=>’2044′,’mm’=>’11’,’dd’=>’17’,
‘name’=>’Undergo First Major Rejuvination Treatments’,
‘info’=>’Certainly there will be many improvements to personal health management before this date, but this is the anticipated date of my first major operation (or likely, full system nanobot integration)’,
‘type’=>’fitness’
),
array(
‘yyyy’=>’2079′,’mm’=>’11’,’dd’=>’05’,
‘name’=>’Engage Dyson Sphere’,
‘url’=>’http://en.wikipedia.org/wiki/Dyson_sphere’,
‘info’=>’If not on the team that deploys it, I will at least be celebrating the event :)’,
‘type’=>’social’
)
);

$types = array();
foreach($events as $event){
if(empty($types[$event[‘type’]])) $types[$event[‘type’]] = 1;
else $types[$event[‘type’]]++;
}
ksort($types);
$typeLinks = ”;
foreach($types as $key=>$val){
$typeLinks .= ‘‘.$key.’ (‘.$val.’)‘;
}
?>

The PHP/HTML

Of course, you will need to make sure you include jQuery. I recommend using the Google Hosted Ajax Library rather than hosting it yourself. There are many good reasons to do this (blog post soon to come).
Just place this either in your HTML head or just before your closing body tag:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>

I’ve used PHPDoc blocks to supply inline documentation throughout the code. Post a comment with any questions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<?php 
$pageName = 'plan';
$pageTitle = 'The Future as I See It';
include('header.php'); 
 
/**
 * get the years and days until a date
 * this function is a bit of a hack until my server supports PHP 5.3.0
 * which has date_diff, alias of DateTime::diff (http://www.php.net/manual/en/datetime.diff.php)
 */
function getUntil($year,$month,$day){
	$year = intval($year);
	$maxYear = 2035;
	$addtime = 0;
	if($year > $maxYear){
		$diffYears = $year - $maxYear;
		$year = $maxYear;
		$addtime = $diffYears * 31536000; // years of seconds
	}
 
	// count leap years
	$numYears = $year - date('Y');
	$leaps = floor($numYears/4);
	$addtime -= $leaps * 86400; // subtract these excess days (to get accurate year count)
 
	$date = mktime(0,0,0,$month,$day,$year) + $addtime;
	$now = time();
	$days = ceil(($date - $now)/86400);
	if($days < 365){
		return 'in '.$days .' day'.($days==1?'':'s');
	}else{
		$years = floor($days/365);
		$days = $days%365;
		return 'in '.$years.' year'.($years==1?'':'s').', '.$days.' day'.($days==1?'':'s');
	}
}
$events = array(
	array(
		'yyyy'=>'2010','mm'=>'01','dd'=>'20',
		'name'=>'Move to Magdeburg, Deutschland',
		'info'=>'My family will be moving to Magdeburg to experience living in Germany and to strenghten our deutsche Sprachfähigkeiten.',
		'type'=>'travel'
	),
	array(
		'yyyy'=>'2010','mm'=>'06','dd'=>'15',
		'name'=>'Produce an iPhone App',
		'info'=>'This might get done before I move to Magdeburg but this is my personal deadline for a v1.0 release.',
		'type'=>'work'
	),
	array(
		'yyyy'=>'2013','mm'=>'07','dd'=>'15',
		'name'=>'Accomplish a Free-Standing Backflip',
		'info'=>'I\'ve done it on a trampoline and with spotters but never alone without aid. This is a life-long goal.',
		'type'=>'fitness'
	),
	array(
		'yyyy'=>'2017','mm'=>'09','dd'=>'01',
		'name'=>'Publish First Novel',
		'info'=>'Contact me if you want to be one of my pre-publication reviewers',
		'type'=>'creative'
	),
	array(
		'yyyy'=>'2021','mm'=>'07','dd'=>'22',
		'name'=>'Give First TED Talk',
		'info'=>'On what topic? Web, security, social media, nano-technology, engineering, the future, productivity in an age of overabundance? I\'m not sure yet--but it will be awesome.',
		'url'=>'http://ted.com',
		'type'=>'social'
	),
	array(
		'yyyy'=>'2026','mm'=>'07','dd'=>'22',
		'name'=>'Engineering Degree from MIT',
		'info'=>'Oh, yes, I will be going back to school. Probably many times in my life.',
		'type'=>'education'
	),
	array(
		'yyyy'=>'2044','mm'=>'11','dd'=>'17',
		'name'=>'Undergo First Major Rejuvination Treatments',
		'info'=>'Certainly there will be many improvements to personal health management before this date, but this is the anticipated date of my first major operation (or likely, full system nanobot integration)',
		'type'=>'fitness'
	),
	array(
		'yyyy'=>'2079','mm'=>'11','dd'=>'05',
		'name'=>'Engage Dyson Sphere',
		'url'=>'http://en.wikipedia.org/wiki/Dyson_sphere',
		'info'=>'If not on the team that deploys it, I will at least be celebrating the event :)',
		'type'=>'social'
	)
);
?>
 
<h1><?=$pageTitle?></h1>
<div id="pageFilter">
<a href="javascript:pageFilter('all')" class="active all" title="Show All">show all</a><?php
$types = array();
foreach($events as $event){
	if(empty($types[$event['type']])) $types[$event['type']] = 1;
	else	$types[$event['type']]++;
}
ksort($types);
 
foreach($types as $key=>$val){
	echo '<a href="javascript:pageFilter(\''.$key.'\')" class="'.$key.'" title="Show '.ucfirst($key).'">'.$key.' ('.$val.')</a>';
}
?>
</div>
<ul class="timeline">
<?php
foreach($events as $event){
	?>
    <li class="<?=$event['type']?>">
    	<div class="head">
            <span class="date"><?=$event['yyyy'].'.'.$event['mm'].'.'.$event['dd']?></span>
            <span class="name"><?=$event['name']?></span>
			<?
            if(!empty($event['url'])) echo '[<span class="url"><a href="'.$event['url'].'">more info</a></span>]';
            ?>
            <span class="until"><?=getUntil($event['yyyy'],$event['mm'],$event['dd'])?></span>
        </div>
        <div class="body">
            <div class="info"><?=$event['info']?></div>
            <div class="type"><?=$event['type']?></div>
        </div>
    </li>
    <?
}
?>
</ul>
 
<script type="text/javascript">
function pageFilter(type){
	$('#pageFilter a').removeClass('active');
	$('#pageFilter .'+type).addClass('active');
	if(type=='all'){
		$('.timeline li').slideDown();
	}else{
		$('.timeline li').slideUp();
		$('li.'+type).slideDown();
	}
}
$('.type').bind('click',function(){
	pageFilter($(this).html());					 
});
</script>
 
<?php include('footer.php'); ?>

The CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#pageFilter {
	font-size:.8em;
	text-align:right;
	margin-top:10px;
}
#pageFilter a{
	border:1px solid #dde;
	padding:3px 5px;
	margin-left:5px;
}
.timeline {
	list-style:none;
	font-size:.8em;
}
.timeline li{
	margin-top:10px;
	border:1px solid #9cf;
}
.timeline .head {
	background-color:#def;
	padding:3px 5px;
}
.timeline .body {
	padding:10px;
	position:relative;
}
.timeline .date{
	color:#036;
	font-weight:bold;
	margin-right:10px;
}
.timeline .name{
	color:#666;
}
.timeline .until{
	float:right;
}
.timeline .info{
	padding-bottom:15px;
}
.timeline .type{
	position:absolute;
	bottom:0;
	right:0;
	border:1px solid #dde;
	background-color:#ffe;
	padding:3px 3px 3px 5px;
	cursor:pointer;
}
a.all, .timeline .all .type{
	background-color:#FFFFFF;
}
a.creative, .timeline .creative .type{
	background-color:#F0FFFD;
}
a.education, .timeline .education .type{
	background-color:#EEF4FF;
}
a.fitness, .timeline .fitness .type{
	background-color:#F2EEFE;
}
a.social, .timeline .social .type{
	background-color:#FDF5F5;
}
a.travel, .timeline .travel .type{
	background-color:#FFFDED;
}
a.work, .timeline .work .type{
	background-color:#F3FFEB;
}

follow on Twitter