Monthly Archives: December 2017

Some thoughts about privacy and networked computers

According to the Merriam-Webster dictionary, privacy is:

a : the quality or state of being apart from company or observation

b : freedom from unauthorized intrusion

Historically, the most common use of this term was around one’s physical space. If you go into a room in your house and close the door, you are experiencing privacy. You are “apart from” others. They cannot see you, hear you, etc.

If you go and sit in your back yard, then depending on the visibility of your back yard to neighbors and passersby, you are experiencing some degree of privacy.

If you send a letter to a friend (the kind that is written on paper and wrapped in an envelope), you have an expectation of privacy in that you expect that your letter will not be read.

In each of these cases, there is a physical barrier that separates the space that you (or your communications) occupy from space that is available for other people to see and observe.

In each of these cases, the physical objects in question do not broadcast information. There is visual information available to any passersby or other residents of the home, but the passerby must take action to look, to seek it out.

It seems that historical notions of privacy have to do with physical presence and a third party must make an effort to transgress a boundary that you have explicitly put in place (a door, wall, envelope, etc.).

Networked computers do not have any of these characteristics!

A networked computer is, in essence, a beacon that is constantly shining in the night. Networked computers constantly transmit information to other computers, and you have to do a lot of work if you want to keep that from happening (and you will probably not succeed anyway, even if you have a lot of relevant expertise). To use the beacon metaphor, it is shining all of the time, you have to do a lot of work to keep it covered up, and any slip of the covering means you will be visible from many miles away.

This flips the notion of what we historically think of as “privacy” completely on its head. Rather than a third party being forced to transgress a boundary to see you in a private room, tear open your letter’s envelope, or jump your backyard fence, the third party running the computer network that you connect to, or the server that your browser connects to, would have to explicitly take action to drop information on the floor that they have already been given.

This is a fundamentally different thing to ask for. In the first case, you are saying, “please don’t cross this physical boundary”. In the second, you are saying “I am sending you this information, but please don’t read it. Well actually, that won’t work — you will have to read it to provide me the service I’m asking for. But after providing the service, please go back and erase the information. Definitely don’t store it anywhere.”

Whereas in the first case you were asking the third party to simply avoid a behavior, in the second case you are asking the third party to do work on your behalf. This is going to be fundamentally harder to accomplish, and you really need to understand that you are asking someone else to do something for you. Implied in asking someone else to do work on your behalf is that they are not obligated to do that work, except under certain conditions or relationships.

You almost certainly do not enjoy these conditions or relationships with network operators, computer manufacturers, the writers of web browsing software, web applications, or advertising technology. You are not in a position to demand extra work from these entities.

Another way of looking at it is: given a possibility space of all behaviors in the physical realm, traditional privacy just carves out a small area of the total space and says “don’t go here”. It looks like this:

privacy-venn-01

Given the possibility space of all of the behaviors that can be engaged in by networked computers, “privacy” carves out an area of the total space and says “you will have to go here at least once to provide me with network connectivity and other services, but I want you to then take a second pass over that area and erase/drop the information you collected during the first pass”.

privacy-venn-02

I hope the above explains why I do not really like or agree with the use of the word “privacy” in discussions about computers. It’s the wrong word. I don’t know if we even have a word for what we need going forward.

Advent of Code 2017, Day 2

This is my solution for Day 2 of this year’s Advent of Code.

You may also enjoy browsing the Day 2 solutions megathread on Reddit.

PROBLEM

The spreadsheet consists of rows of apparently-random numbers. To make sure the recovery process is on the right track, they need you to calculate the spreadsheet’s checksum. For each row, determine the difference between the largest value and the smallest value; the checksum is the sum of all of these differences.

For example, given the following spreadsheet:

5 1 9 5
7 5 3
2 4 6 8

The first row’s largest and smallest values are 9 and 1, and their difference is 8.

The second row’s largest and smallest values are 7 and 3, and their difference is 4.

The third row’s difference is 6.

In this example, the spreadsheet’s checksum would be 8 + 4 + 6 = 18.

SOLUTION

(define (line->list line)
  ;; String -> List
  (let ((read-ln (field-reader (infix-splitter (rx (+ whitespace)))))
        (in-port (make-string-input-port line)))
    (receive (record fields)
        (read-ln in-port)
      (map string->number fields))))

(define (read-spreadsheet file)
  ;; File -> List[List[Number]]
  (call-with-input-file file
    (lambda (port)
      (let loop ((line (read-line port))
                 (results '()))
        (if (eof-object? line)
            results
            (loop (read-line port) (cons line results)))))))

(define (main prog+args)
  (let ((rows (read-spreadsheet "/Users/rloveland/Code/personal/advent-of-code/2017/02/02.dat")))
    (write (apply + (map
                     (lambda (row)
                       (let* ((xs (line->list row))
                              (min (apply min xs))
                              (max (apply max xs)))
                         (- max min)))
                     rows)))
    (newline)))

Advent of Code 2017, Day 1

This is my solution for Day 1 of this year’s Advent of Code.

You may also enjoy browsing the Day 1 solutions megathread on Reddit.

PROBLEM

The captcha requires you to review a sequence of digits (your puzzle input) and find the sum of all digits that match the next digit in the list. The list is circular, so the digit after the last digit is the first digit in the list.

For example:

  • 1122 produces a sum of 3 (1 + 2) because the first digit (1) matches the second digit and the third digit (2) matches the fourth digit.

  • 1111 produces 4 because each digit (all 1) matches the next.

  • 1234 produces 0 because no digit matches the next.

  • 91212129 produces 9 because the only digit that matches the next one is the last digit, 9.

SOLUTION

(define captcha-input "5994521226795838")

'(set! captcha-input "1111")

'(set! captcha-input "1122")

'(set! captcha-input "1234")

'(set! captcha-input "91212129")

(define (gather-matches s)
  ;; String -> List
  (let ((in-port (make-string-input-port s)) (count 0) (head #f) (vals '()))
    (let loop ((cur (read-char in-port)) (next (peek-char in-port)) (count count) (vals vals))
      (if (eof-object? next)
          (if (char=? cur head)
              (cons cur vals)
              vals)
          (cond ((= count 0)
                 (begin
                   (set! head cur)
                   (loop cur next (+ 1 count) vals)))
                 ((char=? cur next)
                 (loop (read-char in-port) (peek-char in-port) (+ 1 count) (cons cur vals)))
                (else (loop (read-char in-port) (peek-char in-port) (+ 1 count) vals)))))))

(define (main prog+args)
  (let* ((matches (gather-matches captcha-input))
         (matches* (map (lambda (c) (string->number (string c))) matches))
         (sum (apply + matches*)))
    (begin
      (format #t "MATCHES*: ~A~%" matches*)
      (format #t "SUM: ~A~%" sum))))