Monday, July 11, 2022

Code: Kotlin First Impressions

Introduction
Kotlin is one of the newest and most popular JVM languages and it might be one of my new favorite languages. Disclaimer: I haven't written much production-ready code in it yet.

As a JVM language like Scala, Groovy, and Clojure; Kotlin tries to take the portability of the Java Virtual Machine and familiarity of the Java language while improving upon its archaic design with the conciseness and power of modern programming languages. Simply put: it's Java but better—for real this time!

Scala was my favorite attempt at improving Java, but I was pretty unhappy with the build system. Since Kotlin is written by JetBrains, an IDE company, compiler and IDE support is first-class. You can even use JetBrains' IntelliJ to output Kotlin code to Java, and vice versa. For this reason alone, it is easy to pick up for Java developers.

Improvements on Java 8
So what does Kotlin improve upon? Firstly, Java's verbosity. Compare a hello world program in Java:

public class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello world!");
  }
}

and in Kotlin:

fun main() {
    println("Hello world!")
}

The first thing to note is that no class definition is required. You can simply add top-level functions. Kotlin is a functional language, so a function definition is required, but the public access modifier is implied. Top-level functions are always static. And type inference also applies to functions, so no void is required here. Just fun to mark that it's a function. In the actual function itself, println is a top-level function, so no need to qualify the function with a package and class. Lastly, no semicolons.

This is not some neat trick about hello world programs, the rest of the language is written to be concise. Record classes (data classes), raw strings, type inference, default function parameter values, string interpolation, collection builders, array slices, range operators, and null safety operators all help make your code very concise and efficient. If you don't know what those mean take the following Kotlin code:

fun doSomething(param: String = "default") {
  val stringTemplate = "$param ${1 + 2} String"

  val nums = (0..20).toList() // A list of integers from 0 to 20
  println(nums.slice(1..5 step 2)) // Prints "[1, 3, 5]"

  val newStr: String? = getStringOrNull()
  println(newStr?.length) // Prints length or "null" if string is null

  val neverNull = getStringOrNull2() ?: "" // Converts nulls to ""

  val regex = """\w+@gmail\.com"""
}

Doing this in Java 8 without special libraries would be like:

public static void doSomething() {
  doSomething(null);
}

public static void doSomething(String param) {

  param = (param == null) ? "default" : param;
  String stringTemplate = String.format("%s %d String", param, (1 + 2));

  List<Integer> nums = IntStream.rangeClosed(0, 20).boxed()
      .collect(Collectors.toList()); // It's either this or a for loop

  // A for loop is simpler than the stream version
  List<Integer> slicedList = new ArrayList<>();

  for (int i = 1; i <= 5; i += 2) {
    slicedList.add(nums.get(i));
  }
  System.out.println(slicedList); // Prints "[1, 3, 5]"

  String newStr = getStringOrNull();

  System.out.println((newStr == null) ? null : newStr.length());

  // We need two lines for this, unless we call the function twice
  String intermediateVar = getStringOrNull2();
  String neverNull = (intermediateVar == null) ? "" : intermediateVar;

  String regex = "\\w+@gmail\\.com"; // We must escape special characters
}

Or at least that's my interpretation. With Java 8 streams, there are a few functions to create and manipulate collections. You can also short circuit nullable objects with Optional.ofNullable([nullable]).orElse([default]), but I prefer the ternary operator in Java.

Another great feature is destructuring declarations. In Python, you can return multiple values. In Kotlin, we get half of that feature by being able to "destructure" a returned value into multiple variables:

  val (name, age) = person
  for ((key, value) in map) {
    // stuff
  }

Lastly, it is interoperable with Java. You can call Java code from Kotlin and you can even call Kotlin code from Java. One of Java's biggest strengths is the massive set of libraries you can use. These libraries are available, too, in Kotlin.

Drawbacks
Sounds too good to exist? Well, Kotlin has some drawbacks. I probably will come up with more after using the language for a while, but for right now, the drawbacks are minimal.

For one, variable type declarations follow the variable name as in var a:Int. For many of us, we started programming in C, C++, or Java where variable types come before the variable name. I disliked this seemingly arbitrary change until it was explained to me.

When declaring a variable, the variable's name is the most important aspect. When your language has type inference, the type isn't always written. This means variables declarations are generally aligned well, regardless of type declaration or lack thereof. This alignment is maintained for variables (val or var) and functions (fun).

val a = 1   // Infers type from value
val b: Int  // No value to infer type
var c: String = "String" // Optionally specify type
// Infer return type of single-expression function
fun sum(arg1: Int, arg2: Int) = arg1 + arg2

Notice that the val/var/fun keywords are all aligned vertically, as are the names. So while this name-type order will take some getting used to, it's not a bad thing. Pretty much all modern languages (Go, Rust, Swift, Scala, Nim, and Python) use it.

One issue that I dislike is the amount of scope functions. let, run, with, apply, and also are all ways to call a block of code with a temporary scope and each is used slightly differently. This seems like overkill and I don't imagine I'll ever memorize which is which. You don't want to have too many ways to do the same thing in a language, as it makes reading and reviewing code difficult.

Overall, it seems like a very fun, concise language and an upgrade to Java.

Kotlin vs Newer Versions of Java
JetBrains 2021 Developer Study


Having said that, Java has progressed quite past version 8. Java 8 is still the most popular version, according to a JetBrains survey, being used by 72% of Java programmers (users were allowed to select multiple versions). SNYK's survey results says Java 11 slightly outweighs Java 8 with both being around 61%. In either case, the higher versions of Java have little use with both companies saying Java 15 use is around 13%.


SNYK 2021 Developer Study

Java 19 will drop in September, but for a company looking for stability should probably stick with Java 17, as it is will still be the most recent version with Long-Term Support from Oracle. So what does Java 17 add to the language that Java 8 and Java 11 users may be unfamiliar with? I will describe some of the notable language updates, ignoring preview features and compiler and JVM enhancements.

Java 9 to 11 updates:

  • 9: Project Jigsaw: Modular system
    Introduces a module system to the language to define exports and dependencies.
  • 9: Private methods in interfaces
  • 9: Actual immutable collections
    Allows things like Set.of(item1, item2).
  • 10: Type inference
    Introduces var keyword.
  • 10: Root certificates.
    Allows TLS out of the box.
  • 11: HttpClient
    A replacement for HttpUrlConnection.
  • 11: More String and Files methods
    New methods like String::lines and Files::readString.
Java 12 to 17 updates:
  • 12: New methods in String, Files, and Collectors
  • 12: A number formatter
  • 14: Switch expressions
    Makes switch expressions much less verbose.
  • 15: Text blocks
    Allows setting Strings to nicely-formatted multiline blocks of text without inserting pesky "\n".
  • 16: Records
    Allows the creation of data classes with default getters and setters in essentially one line.
  • 16: Pattern matching for instanceof
    Decreases verbosity by allowing the declaration of a variable in an instanceof expression.
  • 17: Sealed classes
    Increases control over class inheritance.
Most of this article was written with Java 8 in mind. It's fair to say that Java has come a long way since then and Java now has more syntactic sugar. Specifically, type inference, text blocks (multiline strings), and records (data classes). However, even these new features are weaker than their Kotlin equivalents:
  • Type inference only applies to local variables, not top-level variables or lambda expressions
  • Text blocks aren't raw strings and will still process escape sequences (i.e. you still have to escape all of your backslashes). Writing regex in Java still sucks.
  • A record cannot contain any private instance variables. Admittedly, this is a tiny disadvantage.
Even the work that has been done to modernize Java doesn't bring it up to par with Kotlin. That's why I'm excited to start using Kotlin.

Monday, May 2, 2022

Code: Java Generics: Bounded Wildcards

Java wildcards are the kind of fun that make you want to bathe with your toaster. But they're not so bad if you can remember the simple rules, which come with practice. Say we have three generic lists, one of some random class, one of its superclass, and another of a subclass of the original class:

List<Number> ln;
List<Integer> li;
List<Object> lo;

Then, using wildcards, we can create some wildcard lists. One that uses "extends" of the original class, and the other that uses "super" of the original class.

List<? extends Number> numProducer;
List<? super Number> numConsumer;

Can you remember which of the top 3 lists can be assigned to these two wildcard lists? Don't forget PECS: Producer-extends, Consume-super.

// same type
numProducer = ln;
numConsumer = ln;

// subtype
numProducer = li;
// numConsumer = li; // doesn't compile: Integer isn't a superclass of Number

// supertype
// numProducer = lo; // doesn't compile: Object doesn't extend Number
numConsumer = lo;

Remember that ? extends Number and ? super Number can both be set to an object of type Number. If you remembered that, this was probably an easy exercise. The Java compiler prevents you from making class casting mistakes, so 
you can't set a super to a subclass and you can't set an extends to a superclass.

This might seem weird. If you can set numConsumer to a List<Number>, why can't you set it to List<Integer>? Every Integer is a Number, so any operation you could perform with an item from numConsumer should work. But don't think of numConsumer as a random collection of Numbers and other instances of Number's superclasses. Instead, remember the entire point of writing a lower-bounded wildcard is that the unknown type is indeed known at compile time and we want to restrict the type to only Number and Number's superclasses. Why might we want to do this? Abstraction.

The reason for restricting numProducer to subclasses of Number is even more obvious. If we set numProducer to a list of Objects, we might try to perform numeric operations on a list containing Strings, or Sets, or other non-Numbers.

You really shouldn't be setting any wildcard values directly anyway. They're usually used as method parameters and you simply get things out of (produce) or put things into (consume) your wildcard object. Like in:
public Number addThese(List<? extends Number> addends) {
Number sum = 0;
for (Number n : addends) {
sum = addTwoNumbers(sum, n);
}
return sum;
}
Notice that we're getting the value out of our producer. What type of objects can we get out of wildcard producers and consumers, and what type of objects can we put in to each?

Getting objects out:

Number num1 = numProducer.get(0);
// Number num2 = numConsumer.get(0); // doesn't compile; could return non-Number
// Integer int1 = numProducer.get(0); // doesn't compile; could return non-Integer
// Integer int2 = numConsumer.get(0); // doesn't compile; could return non-Integer
Object obj1 = numProducer.get(0);
Object obj2 = numConsumer.get(0); // Fine only because everything is an Object 

The last line only works because I couldn't think of 3 levels of classes where the parent class wasn't Object. If we used a different super class, an implicit cast from a consumer to its parent class wouldn't work:

// First create two wildcard Integer lists, then get an object from them
List<? extends Integer> intProducer = ...;
List<? super Integer> intConsumer = ...;
// Number numA = intConsumer.get(0); // doesn't compile; could return non-Number
Number numB = intProducer.get(0); // just to show this still works

This makes sense. We can only set value to its type or a subtype of its type. So only a producer can properly use getter methods like get() and only for its type or a superclass of its type. Consumers can't use getter methods (unless you implicitly cast to Object). So if producers can be informally thought of as read-only, consumers are write-only.

Putting objects in:

numConsumer.add(ln.get(0));
// numProducer.add(ln.get(0)); // doesn't compile; producer might be set to diff subtype
numConsumer.add(li.get(0));
// numProducer.add(li.get(0)); // doesn't compile; might be set to subtype
//numConsumer.add(lo.get(0)); // doesn't compile: might be set to subtype
// numProducer.add(lo.get(0)); // doesn't compile: Object doesn't extend Number

This time, it's only the consumer that can add any type of Number or Number subclasses. None of the producer calls work because whatever type the producer is set to, it could be incompatible with what it's getting.

Note that some of these examples would work if you added explicit casts.

Now, for reference, here's a cheat sheet with compilable code.

Thursday, April 7, 2022

Software Engineering: RAED for Permissions

 In any given important software being used by many people, access control is an important part of security. For example, I have the proper permissions to edit this blog and you do not.

But there's many ways to implement access control. For example, Unix-like file systems generally have read-write-execute permissions. A user, group, or "other" can each have a combination of permissions to read, write, or execute a file. An admin might use the chmod command to edit a user's permissions.

Windows implements file access control differently. There are permissions such as "Full control", "Modify", "Read & execute", and just "Read" that can be allowed or denied to a user or group.

Windows File Permissions

CRUD is another way permissions might be implemented. A user can be allowed to create, read, update, or delete files or other types of data in any combination.

At my last job I was tasked with coming up with an authorization system for our microservices. Rather than use some framework for authorization, I decided to build our own. I was replacing WordPress permissions, which were similar to CRUD. For any given type of page, a user might be allowed any combination of the creation, reading, updating, or deleting permissions, depending on what an admin had checked. For example, our online magazine had CRUD permissions. All of our customers could read the magazine. Specific content creators could create new articles and upload them. Editors could update anyone's articles to fix grammar, spelling, or links. Finally, admins could delete articles.

Designing permissions was important. We didn't want to give a user the wrong set of permissions, otherwise they might be allowed to delete important data. Or, with insufficient permissions, they might not be able to do their job.

I decided to use something I had previously created: RAED, a superior access control design for general-use permissions.

RAED stands for read-add-edit-delete and is a set of eclipsing permissions to be used with file systems, RESTful APIs, or anything else that requires access control. It's basically CRUD, but much better.

Other permissions become confusing when certain combinations are used. For example, what does it mean when you can write something, but you cannot read something? When would you be allowed to delete data without being able to update it?

With RAED, there is no confusion because if you have one level of permission, you have all of the permissions below (or to the left of) it. If you can add, then you can read. If you can edit, then you can read and add. And finally, if you have the delete permission, you also have the read, add, and edit permissions for that particular thing. For any given permission level, just makes sense to have the lower permission level. When will a user need to delete data, but should be forbidden from reading or editing that same data?

RAED is simpler to display. Instead of four sets of radio buttons (Allow/Deny) in CRUD, you have five radio buttons (the first one being no permissions). Example:

Database Permission:

RAED doesn't work for all access control systems and permissions, for example, when you only need a simple binary Yes/No for Can-Upload-Photo-Permission or similar. However, if this meets your needs, I highly encourage you use RAED.

Wednesday, March 23, 2022

Security: Choosing and Storing Passwords

Best: Password Manager
It's 2022. Everybody should be using a password manager to store and randomly generate different complex passwords for each website they use. There's a lot of good options on this front. Even the simple password managers built into your browser work pretty well. For most people, using Google Chrome, Mozilla Firefox, or iCloud Keychain is sufficient.

If you want to use a third party for whatever reason, LastPass served me well, although the free tier only allows you to store passwords on one device: mobile or desktop. I am now using 1Password, which is almost perfection, although it costs $3 per month.

I could write a whole article about which password manager is best, but the important thing is to use one. They generate secure passwords instantly, obviate the need to remember more than one password, store your passwords in a secure location, seamlessly sync mobile and desktop (except LastPass free tier), and tell you how secure each password is. Many password managers have other features like reporting to you when a password was found in a breach, informing you of your reused passwords, and keeping a history of used passwords.

But if you must, I'll list some other options.

How Hackers Crack Passwords
Before we get into how to generate a fancy hard-to-guess passwords, let's talk about why we're doing this and not just using "Password1!" for all your passwords.

The first way a hacker might get access to your account is to just guess your password. If it's just your name backwards, that's easy enough to guess. In fact, that was the password to my brother's electronic organizer in the 1990s (don't tell him I cracked it!). Similarly, hackers know to guess "password", "123456789", "qwerty" and other similar easy passwords.

Assuming the website you're using has good security (uses good hashes, with salt, etc.) another way a hacker might try to guess your password is to reuse one of your passwords from a website with bad security. For example, until a few months ago I still had an email account at excite.com, which had an insecure login page. That means anyone with basic hacking skills could steal my username and password for that site. Obviously, no one uses Excite for anything important anymore, but people do reuse passwords from site to site. If I reused my Excite password elsewhere, I'd be begging to be hacked at those other sites.

Lastly, a hacker might crack your password by simply trying all possibilities aka brute force. If the website you're using doesn't have very good security, a hacker can try different passwords rapidly. In fact, hackers can try a billion different passwords per second. Here's a chart showing how the speed of a cracking password is related to password complexity.

Chart from Hive Systems

This is why many websites require a password of at least 8 characters that must comprise uppercase letters, lowercase letters, numbers and symbols.

Next Best: Hidden, Secured Password Documents
As we have shown in the previous section, passwords should not be guessable, should not be reused across different sites, should have at least 8 characters, and should be composed of different types of characters.

The next best option to using a password manager is to generate these passwords yourself and keep them in a secure location. There are plenty of password generators on the Internet (ahem). The question is: how will you store your passwords securely? Your passwords are surely too complex to remember. You should also have access from your computer as well as from your phone.

For a while, I stored all my password in a text document that I uploaded to a mobile app. I changed the extension on the text document, so it wouldn't open in a word processor. The mobile app (IDrive) was secured with a password, so no one could open it without knowing one of my passwords.

This was a decent way to store my passwords, but was cumbersome and meant I had to manually sync my passwords by uploading my password file every time I changed or added a password. For those of you who don't like or trust password managers, this might work.

Perhaps Instead: Easy-to-Remember Passwords
There are several easy to guess password ideas:

In an ideal world you could simply remember your passwords using these hacks.

Actually...
But you won't. Memorable passwords won't work. The average person has 100 passwords, and whether you use the password generator or something super memorable, it doesn't matter: you simply won't remember all of your passwords. Secured storage is key and you can't get better storage than a password manager, as mentioned above. If you're very meticulous and organized, maybe you might not need a password manager, and instead can do something like I mentioned above with a hidden text file uploaded to the cloud.

But chances are you're not going to do that. You're going to have a Microsoft Word document or a physical notepad full of your passwords. And that's fine if no one ever will have physical access to your machine. But that won't fly at a professional workplace, on shared computers, or on a laptop owned by someone who travels a lot.

For most people in the modern world, a password manager is a necessity.

Saturday, November 27, 2021

Job Seeking: Crafting the Perfect Resume

In this economy, job seekers are at an advantage. Businesses are desperately seeking employees, not just in the service industry, but also in the tech industry. But that doesn't mean it's not important to put your best foot forward and craft the perfect resume that highlights your talents.

I have interviewed scores of software engineers and managers across three companies over a 13-year career. As a director I've made the final call on hiring several QA analysts, QA engineers, and QA managers. I've represented my company at several career fairs. So I know what I want to see in a resume.

This is one area I wanted to make sure I had a lot of experience in before I spoke publicly about it. I feel I have finally achieved that level of experience. Here is my advice.

Basics
A resume should list your skills, your technologies you're familiar with, your work history, and your education. There are a lot of good samples on the Internet. I have posted one below.

Work History
I've been told to make sure I highlight concrete, measurable accomplishments rather than job duties. That is, don't say "Responsible for redesigning backends", say "Streamlined backends, reducing wait time by 50%" if you sped up a backend request from 0.8 seconds to 0.4 seconds. But when I'm reviewing resumes, I am less focused on those achievements since some are easier to accomplish, depending on the company's existing technology. Additionally, many of those tasks were given by bosses and measured afterwards. That measurable accomplishment doesn't tell me much more than a description of the task you were given; it just tells me that you were successful at it. When I read work history, what I'm generally looking for are the technologies worked with, tasks given, and roadblocks overcome.

Similarly, use action verbs. Don't just say "did", "made", and "told". Use "performed", "implemented", and "documented". Once again, I see through that kind of stuff, but it's a good sign when you can use strong action verbs truthfully to describe what you accomplished at previous companies. For example, "documented" implies a permanence that "told" does not. Are they still using your research? Probably so if it was "documented." Probably not if you only "told" someone about it.

Definitely don't sell yourself short. Highlight your top accomplishments and phrase your responsibilities and leadership so that readers don't think you just played a small part in any projects that you led or had a massive part in.

Words Words Words
There is an exception to my apathy to big words: fancy words and flowery grammar show me that you have an excellent command of the English language. If I have any bias, it's a bias towards excellent English communicators. As a software engineer, I have worked with many people who didn't know how to communicate properly and it has occasionally become a stumbling block. It is sublime working aside engineers who can disseminate information widely and individually in a manner that is concise, precise, and unambiguous. Yes, I did use some SAT words there to make a point.

Don't Lie
Oh my god, don't lie. At Google, I once did a "coaching call" (mock interview) with an applicant who claimed he had been the leader of a local student organization. Incidentally, not only had I participated in that same organization, I actually knew the then-leader of the organization. While on the phone with this applicant, I realized something was suspicious and asked for clarification. He backtracked from his lie.

I would never hire someone who would lie about something small like an extracurricular activity. Saying you know Java when you only wrote a small Java app is a small stretch of the truth. Saying you held a leadership position you didn't actually hold is such a meaningless lie that it shows you can't be trusted at all.

Cover Letters: Unnecessary
A cover letter has never, not once, affected whether I wanted to hire someone or not. I understand that there is a level of effort in creating one, but that effort could go towards improving your resume or leveling up your interviewing skills. Anything important to know should be in the resume. Most times, I don't even read cover letters.

Resume Length: 1-2 Pages
It's hard to fit your whole life onto one page, especially if you've been at multiple companies. Now that physical paper is a thing of the past, a two-page resume is completely fine or even expected. Three is a bit long and four is ridiculous, unless you've had a very long, illustrious career. Stick to 1-2 pages. My current resume is 1.5 pages.

Fancy Design
Should you use column headers, multiple colors, a sidebar? I shy away from that. My resume is super plain; maybe even too plain. I do enjoy reading a nice looking resume, but don't go too fancy and make things difficult to read. During my current job hunt, I've filled out online job applications that scan my resume and fill out the application with the parsed results. I imagine these apps struggle on overly-fancy resumes.

An exception is when the role requires good design skills. I am impressed when a frontend developer has a nice resume. This may be foolish, but I suspect the skills in resume design may carry over into web design. But it's not required.

Customize to the Job
If you're applying to different roles, customize your resume. For example, I've applied to QA manager roles and engineering manager roles recently. Each time, I tailor my resume to highlight what the hiring manager wants to see and remove experiences and skills that are irrelevant.

Example
Here's a sample resume from Monster:

I find that most sample tech resumes on the Internet are pretty good, so follow those for the basics.

Thursday, November 4, 2021

Wish List 2021

I've found myself with some free time, so let's talk about tech.

My Phone

I've got an old phone. I'm rocking the OnePlus 6T, a 2018 phone from a Chinese manufacturer. Although it's aging, it suits my needs. Most importantly, there isn't any phone out there with the specs and price to offset my interest in keeping my phone for environmental reasons. I don't want to get on a soapbox here, but buying a new phone every 2 years has a larger carbon impact than keeping your old phoneThe other reason is the cost, as a lot of the flagships are around $1000. I have that kind of money but it seems silly to upgrade when my current phone can do basically everything they can do.

Still, I look at current tech dreamily and wonder what if...

Dream Phone:

  • Screen: Dynamic AMOLED 2X or Super Retina XDR
  • Antenna: 5G
  • Camera: Good camera software
  • Feature: Face ID
  • Feature: In-screen fingerprint reader
  • Feature: Wireless charging

Samsung's Galaxy S 21 screen has 1300 nits brightness and 2,000,000:1 contrast ratio, which is about the same as Apple's iPhone 13 screen. Both operate at 120 Hz, which is nice.

Good camera software is huge. Specs like megapixels don't matter anymore. I'd take the iPhone X's older 12MP camera over my 6T's newer 16MP camera any day. At this point, it's purely software that makes for good lowlight pictures, image stabilization, and color reproduction, rather than megapixels or (as far as I can tell) focal length. Apple is king of the cameras, with Samsung close behind. It'd be nice to have a good camera again. As for number of cameras, 3 is pretty standard now.

Apple's Face ID still seems to be the best implementation of a 3D face unlock mechanism. Some Android phones have 3D face unlocks, but they don't seem to have the security of Face ID. I'm pretty sure my 6T's face unlock is 2D and can be fooled with a photograph of my face.

Face ID would be nice, but it still can't compare with the security of a fingerprint reader, especially given that everyone is wearing a mask nowadays. Surprisingly, the iPhone has no fingerprint reader while even my basic 6T has a fingerprint reader in the screen.

Wireless charging is the last thing on my list. It's also quite standard, but my current phone doesn't have it, so it's worth mentioning.

Everything else I don't care about. Storage, battery, etc. I don't care about. They're all pretty good. I'm never going to use all 256 GB available on some phones. My current phone has around a 9 hour battery life. The long-lasting iPhone 13 Pro Max's 12 hours isn't really make a huge difference to me. Either way, I'm charging my phone every night and putting on battery saver before I get to bed. I'd like an audio jack, but everyone's getting rid of it. I don't know enough about chips to say which processor is best, and my current phone was fast enough when I bought it. Operating systems are all good. Android isn't fragmented anymore, not really and iOS has so many good features I'd consider it, despite the walled garden.

We're really getting to a point where any mid-tier phone is good enough for me.

For some lulz, let's look at my last phone wish list post from 2011:

  • OS: Stock Android 4
  • Processor: Quad-core
  • Expandable Memory: Micro SD slot
  • Display Tech: Super AMOLED Plus
  • Display Resolution: Full HD
  • Display Size (horizontal): 4.3 - 4.5"
  • Thickness: <9mm
  • Battery Life: 10 hours talk time
  • Charging/Connectivity: Micro USB or MHL
  • Video Out: Micro HDMI or MHL 
  • Back Camera: iPhone 4S or Nokia N8 quality
  • Front Camera: 5 megapixels
  • 4G: LTE or T-Mobile HSPA+
  • Design Other: Camera button, Kickstand
  • Other: Gorilla Glass or Fortified glass screen , DLNA, NFC,  Pixel Qi?
  • Price: $200

lol. We've grown fond of our huge phones now, but I do miss camera buttons and audio jacks and $200 flagship phones.

Sunday, August 15, 2021

Code: Easy-to-Type Password Generator





----

People who care about security use hard-to-crack passwords, generally generated by a password generator to have a random mix of uppercase letters, lowercase letters, numbers, and symbols. Those four requirements are often required for website passwords, along with a minimum length and other requirements. However, a password like 3gK*&>5%bZY)sH:D can be hard to type, especially on certain devices. For example, typing out passwords for video game consoles is a huge annoyance, as you generally have to hunt and peck with a cursor across a software keyboard. That cursor is controlled by your video game controller. This can be more difficult than a hardware or a capacitive touch (mobile) keyboard, which are both controlled directly with your fingers and you can input multiple letters in rapid succession.

The on-screen keyboard on a PlayStation 4. You must press a button to access capital letters or for the symbol keyboard. I don't know why there are there two f's on this keyboard.

It would be easier to type such passwords with a better keyboard. But since we can't use our phones to input passwords to our game consoles, nor do we want to pay for expensive game console keyboards, it's simpler to just generate a password that's easy to type. What would make the passwords easy to type? Putting all the types of characters next to each other. Uppercase letters go in one continuous section of characters, lowercase letters go in another section of characters, numbers are colocated, and all symbols also go next to each other. This way, you're not constantly switching the keyboard type for every character you input, only each section.

What about security? You can still keep good security by having a password be long, using a crypto-safe pseudorandom selection, not only for each character, but the order of the character type sections. If you like, you can add extra sections, picked randomly of course. A password of 3045krkfEYTB{+:_ is hard to crack. A bad actor doesn't know the order of the sections, nor do they know which characters are selected within each section.

Meanwhile, you only switch keyboard types (from default to number* to lowercase to uppercase to symbols) a maximum of four times. That's way fewer than the 13 keyboard switches needed to type 3gK*&>5%bZY)sH:D, a password of equal length. It's more secure than the easy-to-type password, but the easy-to-type password is already secure enough (takes years to crack).

If you want to see exactly how secure the algorithm would be, let's compare:

Assuming you have 27 symbols, there are 27+10+26+26=89 different characters to choose from with a regular password. A password of length 16 means there are 89^16=1.5e+31 or 15 nonillion possibilities. A high number for sure.

With an easy to type password of four sections (minimum) and a length of four characters per section (default), let's first calculate the permutations on the sections P(4,4)= 24. Then each section has 4 characters, allowing repeats. For digits that's 10^4 = 10,000. Each set of letters is 26^4=456,976. Symbols is 27^4=531,441. Multiplying those together gets you 2.6e+22 or 26 sexillion possibilities. The easy-to-type password is less than a regular 16-character password by 9 orders of magnitude, but it's still quite tough to brute force. And that's if your hacker already knows you're using this generator with the default settings.

Compare it with the much more popular 8-character password, which has roughly only 3.0e+15 or 3 quadrillion possibilities (number of symbols varies). The easy-to-type password is stronger by 7 orders of magnitude. And you can play with the number and length of the sections to make it even stronger. Keep in mind, you still have to switch keyboard types many times when typing in the traditional 8-character password, even if you have to switch fewer times than with a 16-character password.

Because I was interested in this idea, I decided to code it up in JavaScript, and because I like getting to the point, I posted my implementation up above. I set the section length minimum to 1 in case users want to generate a regular-style password, but if using a section length of less than 4, I highly suggest using 8 or more sections. Passwords are generated completely client side; I don't save or send the results anywhere at all.

You can also find the code at: https://github.com/omaric/easytypepass

* I suppose there isn't a numbers-only keyboard type on most onscreen keyboards. Still, I think numbers deserve their own section in this password generator.