Showing posts with label computing. Show all posts
Showing posts with label computing. Show all posts

Monday, May 27, 2024

Why the Xerox Star failed

"That trick never works!" - Rocket J. Squirrel

or

Single-purpose machines built by lone geniuses for other lone geniuses don't scale.

The Xerox Star was an attempt to commercialize the pioneering computers that emerged from Xerox's PARC labs in the 1970s.  They started with machines called the Alto, and continued with Dorados, Dolphins, Dandelions, and Daybreaks, which came to be called D-Machines, all running (mostly) the same software.  They were a marvel for their day, and had all of the components of today's windowing PCs from Apple and Microsoft, but years earlier. The story of how the Star came to be and how Xerox came to abandon it is a complex one, and like the system itself, the full story is distributed across many obscure places that are not entirely consistent with each other.

But I think that the big picture reasons for its failure get lost in the soap opera details, and are worth a few words.  Obviously, Star had to be released too soon for its technology. Many of the reasons for its lack of broad adoption can be traced to the speed of its underlying electronics; and much of the architectural and usability weirdness of the various models of computer in its history can be traced to attempts to compensate for this basic problem.  Fifteen years later, Apple introduced the Macintosh, with almost the same capabilities, but with a commodity microprocessor CPU instead of custom designs made from bit-slice processor elements, at a tenth the price.  The Star had died out by then, but the Mac continues on to this day.

What kicked the Mac over the top into the realm of success was its developer ecosystem.  Technically, the Macintosh and Star developer models were very similar.  In the early days of the Mac, it wasn't possible to use it for development of its own Mac software -- developers had to use the substantially more expensive and powerful Lisa, and then test and distribute their applications on a separate Macintosh unit.  This was the same process that had been used for the Star, where developers used a Mesa development environment, and then deployed the results to the Star environment.

The difference was that there were already a lot of Apple II developers who were excited to move up to the new and awesome Lisa system.   I was a grad student when the Lisa was released, and one of my friends got one -- he must have spent a substantial part of his meager life savings on it.  The business and research communities that were available to Xerox in its own time could not match that kind of commitment.

The community that developed the Star was small and exclusive. I happened to be attached to a PARC-adjacent computing community in the mid 1970s and there were rumors of amazing things going on over there, but exactly what was never clear. It was impossible to tell from the outside, but much later it emerged that the PARC computing community was internally even more fragmented than it appeared to be This turned out to be typical for an entire stream of computer research history, but the phenomenon was particularly acute at PARC, and its effects showed up in fundamental aspects of the D-machine architecture.

Notably, there wasn't really a "D-machine architecture". There were high-level visions of what might be possible in a world where every person had their own computer beside their desk, but everyone had a different version of that vision. PARC had been staffed with some of the most brilliant, creative, and independent computer researchers to be found, and they created Promethean hardware frameworks that could be elaborated into whatever their application vision required.

The result was that a given D-machine could become one of four different computers, depending on who was using it at any given time. A relatively tame instance provided for programming in the BCPL, Mesa, and Cedar languages under the control of a command line interface in its windowed development environment, Tajo. Starting the machine with a different microcode load would turn it into an office workstation providing a suite of word processing and publishing tools with the now-familiar windows, icons and folders metaphors, but without software development ability. Other microcode created a  Lisp Machine running Interlisp-D, or a dedicated Smalltalk machine. The microcode and even the device drivers for each environment were unique and incompatible and the user communities for each one didn't seem to talk to each other, and their writings rarely even acknowledge their counterparts' existence.

A D-machine gave its user a vast amount of control and flexibility -- it could become whatever you could imagine, if only you had the talent, skills, and time to build it before your tenure at the lab expired and you had to go somewhere else. Collecting brilliant people and giving them access to the most advanced tools and letting them work on whatever they think they can be the most productive at is a standard strategy for top tier research labs, and it often produces marvelous results. PARC produced many marvelous things. However, creativity is unpredictable, and unpredictability is largely unworkable as an element of business strategy.

Xerox management turned out to be unable to solve the problem of herding its houseful of cats in a coherent direction that led to business success, and their inability to settle on a common machine language that would be tolerated by all their diverse projects is emblematic of their failure to achieve focus. Each external developer community was too small to provide Xerox with the volunteer support that it needed in order to attain a critical mass that contributed to business innovation in the way that DECUS or SHARE did for DEC and IBM, or that Apple enjoyed in a less organized way, instead of draining energy and R&D funds.  Whether that critical mass was possible given the other limitations of the technology is impossible to say, but there's no evidence that Xerox or PARC management had any notion that customers could be creative contributors to a product in a way beyond passive consumption.  It would take another two or three technology cycles before the idea of a "platform" became a common sense aspect of business strategy.

Monday, November 08, 2021

Automated social engineering of SMS enhanced authentication

There’s a journalist’s slogan about the threshold for a reportable story that goes something like “Once is an accident, twice is a coincidence, three times is a trend.”  Looks like bots that capture one-time-passcodes sent via SMS without human interaction have passed that level, as a report from Motherboard details.

The NIST has been deprecating SMS as a factor in multi-factor authentication since 2017, because SMS-based OTPs are vulnerable to man-in-the-middle attacks. These attacks are now automated.  Once the attacker has gotten your username, password, and phone number as part of a cache of breached millions that they’ve acquired, they’ll do a partial login to your account on a target system, then the authentic system will send you your SMS code, and the attacker’s bot will phone you and pretend to be the target’s security organization and ask you to confirm the SMS code via your phone keypad.

I found out about this via a finance blog that I follow.  When a security vulnerability has reached a level of visibility that financial pundits are writing about it, it’s time for financial systems to convert to a more secure method.  The report from Intel471 offers some suggestions

More robust forms of 2FA — including Time-Based One Time Password (TOTP) codes from authentication apps, push-notification-based codes, or a FIDO security key — provide a greater degree of security than SMS or phone-call-based options.

Unfortunately, sometimes even simple solutions like physical tokens are unfeasible.  The small town bank that my mother uses has a customer population that is so unsophisticated that they are unable to handle any kind of online authentication more sophisticated than a password, and Mom has trouble remembering hers.


Saturday, September 18, 2021

What's wrong with Haskell?


Whenever discussions of programming turn to functional programming languages, Haskell is invariably brought up as the best example of its kind, or at least the most well-known.  It's eclipsed Lisp, which is a good thing, I suppose, but Haskell has such severe problems in dealing with the real world, it would be an improvement if this were funny.

Maybe that's its most fundamental problem, that functional programming is not for dealing with the real world, it's for dealing with mathematical things, like functions.  When you try to make it deal with the real world, you have to add a bunch of ugly things to the language to get it to cope adequately.

Explaining why this is so could get really long, but you deserve to know what Haskell's top problems are without having to wait for me to write a long essay and then for you to have to read it.  Here, then, are my top peeves with Haskell.

  1. Lazy evaluation of function arguments.  I understand that strict evaluation causes problems when functions are given arguments that don't terminate or have other problems and those arguments are required to be evaluated because they come first, even though they are thrown away at later points in the function that they are given to.  This means that every language that tries to have strict evaluation really needs to have at least one quasi-function that disobeys this rule and does lazy evaluation.  This is usually the "if" function, or a "case" or "cond" function that uses shortcut evaluation and returns as soon as one of its arguments succeeds, before evaluating all them. 
    But lazy evaluation makes it difficult to create a mental model of what a complicated series of function applications ends up doing, because you have to understand the sequence of applications all the way to the end before you can be sure that you've accounted for the effects of all its arguments.  This leads to excessive demands on mental working memory, which leads to programming errors.  Functional programming advocates argue that this isn't a problem, because modeling execution is bad practice; you're supposed to prove properties of the program instead by reasoning about them.
    Lazy evaluation also makes some cool things possible, like potentially infinite data structures that don't cause problems because functions on them always return before running out of data.  In reality, I've only seen one use of infinite data, and that was in Conal Elliott and Paul Hudak's functional reactive programming idea.  FRP used an infinite list of input events instead of an infinite series of "read" function calls inside an IO monad.
  2. Monadic IO. Using the category theoretic concept of a monad to force sequential execution of functions into a lazy evaluation framework where argument application doesn't need to occur in the textual order presented in the program code is a brilliant solution to a hard problem, but it's the wrong answer. Monadic IO is presented as a way to textually encapsulate the side effects of interacting with a stateful world outside of a program, giving freedom from side effects to the rest of the program, but in far too many instances the entire program is wrapped in an IO monad, leaving the stateful side effects just as pervasive as they ever were.
    An alternative design direction would be to think more deeply about the notion of "referential transparency" and build control over referentiality into the language.  Instead of a simple concept like "functions with the same arguments always give the same result" and calling violations of this rule "side effects" to be avoided, go back to W.V.O. Quine's short discussion in the book Word and Object, and understand what's going on as the names "Cicero" and "Tully" are both different and the same as they refer to that guy who lived in Rome 1,900 years ago.
    Control of referential depth exists in languages like C that provide pointers, but as far as I know pointers have never been successfully implemented in a language with strong typing that can prevent "attempt to dereference null pointer" errors at compile time.  Most languages that attempt to deal with this problem do it by eliminating pointers entirely, and create special cases for situations like strings where references are the natural way to deal with the type.  In lisp you have the 'quote and 'unquote forms that partially deal with managing referential depth in a general way, but those work because lisp is dynamically typed.
  3. Strong typing that's not quite powerful enough. Haskell was one of the first functional languages to incorporate strong typing that was powerful enough to be useful, for certain senses of "useful", and that was a significant achievement.  But Haskell's type system is first order, and that causes problems.  It means that flat data structures like vectors and arrays either have to be faked as lists of lists, or restricted to be of unique size.  You can define something like a int_vector_len10, but there's no way to express a type int_vector(size) where the size is defined at compile time.
    Functional languages with type systems that support such parametrized types exist, and their type objects are called "dependent types".  Unfortunately the people who design dependently typed languages are mostly interested in tools for doing mathematics such as proof assistants, not in tools for doing more general things, so their support communities are small and specialized, and they don't evolve the libraries and tooling needed for broad use.  We can only wait and hope that dependent typing technology becomes well known enough that it will migrate into more general purpose functional languages.  Maybe even a future generation of Haskell, who knows?
  4. Pervasive Currying.  Currying allows you to convert functions with multiple arguments into functions with one argument, which is a function of the other arguments.  It allows you to get rid of all those parentheses which are so annoying to people who are just learning lisp.  This is cool, but bad.  Absence of parentheses obscures program structure by requiring a programmer reading an unfamiliar piece of code to look up and keep in mind the type definition of every function that's in use, in order to determine the abstract structure of the code. This introduces a memory burden on the reader that slows understanding and permits misunderstandings of what's going on. In a large program that uses library functions such as those in Haskell's standard prelude, it's a serious problem.
    With parentheses or other delimiters, you can discover the code structure without having to understand the specifics of every element.  Authors of Haskell programs are subconsciously aware of this problem, and use line breaks and indentation to suggest the structure.  But these hints are not required by the complier, and cannot be trusted.

Maybe the right way to think about functional programming, especially with typed functional languages, is that it's a declarative framework for thinking about and expressing provable facts about complex functional expressions.  This is an important goal for programming and creating tools that facilitate it is an admirable endeavor. The fact that those expressions can be executed and produce results is almost an irrelevant afterthought.

Declarative programming entails a radically different mindset from programming in a style that reflects the hardware structure of computers.  Many smart people believe that its better to think in this style than in a more conventional style.  But maybe you thought that computers could be used to interact with the real world, and maybe even model its behavior?  What kind of a wierdo are you?

 

Saturday, June 05, 2021

Avoiding check fraud by closing the identity and integrity assurance gaps

Banks and the companies that banks work with that print paper checks have incorporated a host of anti-counterfeiting measures into those checks, but the use of mobile deposits erases the benefit of those measures.  When you make a mobile deposit of a check that you have received, your phone's camera, which has limited resolution, doesn't have the ability to capture features such as watermarks and microprinting and relay them to the bank for verification.  Then when the bank creates a permanent record of the check image, it throws away even more information and stores only a low-resolution black and white bitmap of it - without even shades of gray.  This is very efficient for storing records of trillions of checks, but it creates an opportunity for forgery.  

The checking system thus relies on accounting integrity as the final detector of fraud of any kind.  As long as the check writer regularly computes their balance, any fraud will be detected, and the specific method of accomplishing that fraud can be identified by working backwards through the steps of check processing and clearing.  This is not really satisfactory, since by the time the fraud has been discovered, the check may have cleared and the funds transferred to the criminal, who has had plenty of time to escape and cover his tracks. 

Forged and altered checks need to be detectable at the time of presentation for payment, not long afterwards.  To do this, they need end to end integrity features that are associated with the check at the time that it is created.  When the check is converted to electronic form by a mobile banking app, the features need to be electronic from the beginning, and associated with the paper check and the person who is creating it as they are writing.

For business checking, where the checks may not be created by a single person, but by software and printers under the control of a team authorized by treasurer or CFO, a large number of business anti-fraud measures have been developed.  Most of these don't provide end-to-end integrity for a check that may be converted to electronic form at multiple stages of processing.  One that does is positive pay (and reverse positive pay), but, it is often implemented in ways that are unsophisticated in both their technology and process aspects, and often works on timescales that do not pretend to approach real-time.  With smartphone-based mobile deposits, it's no longer necessary for a check recipient to travel to a bank or ATM to deposit a check; a check can be deposited within minutes after it is received from the writer, as well as allowing the fraudster to avoid all the video and multiple ID checks that are involved in those other methods.

There are at least five general ways that end to end electronic integrity measures can be added to the checking process.  All of them are extensions and improvements to positive pay, with cryptographic assurance of the values of the check, making altered checks or fraudulently created checks almost impossible.

  1. Interactive positive pay. When a check is created, the person writing the check enters the check's amount, payee and other information into their online banking account, or their mobile banking app.
  2. Smartphone check image preauthorization. When creating a check, the person writing the check snaps an image of it immediately, before delivering it to the recipient.  This function uses much of the same functionality that is already in the mobile app for mobile deposits.
  3. Pre-registered print-on-demand checks. Instead of using a checkbook full of preprinted checks, the online website or mobile app creates a printable image of a check, prepopulated with the values intended to be paid and a digitized version of the writer's signature, and decorated with security features that are unique to this particular check.  The digitized signature is conceptually similar to what happens with mass-produced checks from the government and other sources.  The Secretary of the Treasury doesn't personally sign each one of the tens of millions of IRS refund checks that are issued each year.  The paper result is simply an "original" of the replacement "substitute check" that is already approved for use when an original check had been destroyed by a bank during processing, along with the anti-fraud measures that it incorporated. The per-check security features on the on-demand original can include digital signatures printed in an optically-scannable font along with the MICR account information, in the form of a QR code or other barcode, and additional subtle watermarks in the printing that are designed to withstand the data loss from compression as checks are digitized. And in the process of composing the on-demand check, the website or app creating it can file protected pay data with the issuing bank.
  4. Camera-equipped smart checkbook. Using a smartphone to record a check image as soon as it is written requires the writer to remember that the recording is needed, pull out the phone, open the banking app, focus and snap the photo.  A camera built into a checkbook, connected to the phone via bluetooth, or even with a standalone LTE cellular data subscription, reduces all these steps to a one-button operation and can be designed to provide for the close focus and perspective corrections needed to give highly repeatable images. A nanocomputer board and camera module can cost less than $20, even in small quantities, a cost comparable to a consumer shipment of paper checks with all their security features.
  5. Smart carbons, using a penpad checkbook. The ultimate in usability for check preregistration would be to capture the digital properties of the check from the writer's pen while the check is being written. Using technology like the 2015-era HP Pro Slate with Duet Pen, a checkbook equipped with a special pen and writing surface would provide a user experience identical to the current experience of writing an unregistered check, but with digital security that is fully end-to-end, eliminating the possibility of undetected forgery or alteration.
Trustworthy data on the amount of check fraud occurring in the US annually are hard to find, with estimates ranging from $1.3 billion to nearly $19 billion.  Unfortunately, the many stages and organizations involved in check processing make it difficult for any single participant to justify the investment needed to bring checking security in line with 21st century best practices.  

Alternatives to checks, but with better security

Perhaps the best strategy for a consumer interested in improving their own checking practices is to try to eliminate checking entirely.  Payments that occur regularly can be converted to ACH auto-debit payments, although the ACH system has its own security issues.   

Checking accounts commonly are provided with debit cards used for ATM transactions that can be used for payments instead of ACH debits or checks.  If a debit card is used fraudulently, a new card can simply be re-issued without the hassles of closing the affected account and opening a new one.  Most debit cards come with an explicit zero liability guarantee, as well.

Credit cards are superior to debit cards, since they have a credit limit that will cap the possible damage should the card be used fraudulently. The only way to avoid the trouble of visiting the website of every company that has been setup for autopay and changing the debit to a new card, however, is to obtain a separate credit card for each recurring payment.   (Although if you keep all those cards in the same wallet, someone who obtains your wallet can misuse an amount up to the total of their credit limits.) 

Finally, for person-to-person payments, people with smartphones can use apps like Venmo or Zelle instead of cash or checks. They provide an end-to-end chain of cryptographically assured authentication and integrity checks via the smartphone's security modules and the app's authentication features.  Unlike checks or debit and credit cards, or even ACH transfers, though, there's essentially no way to stop or reverse payment if the recipient acts badly.  They should be used only with people you trust and have continuing relationships with.

Regardless of the improved convenience and security capabilities of check alternatives, paper checks are not going away any time soon.  Users of checks should take advantage of available positive pay and autocarbon features to improve their integrity, and banking and check processing institutions should investigate the further advances that are possible.

Thursday, September 10, 2020

Cybersecurity Doctrine and Strategy: The big picture

Hey, a cybersecurity post!  I've been developing a new security doctrine, Attacker-Oriented Security, that fixes the many problems with popular security doctrines.

Attacker-oriented security recognizes that security events are caused by malicious actors, and that different types of actors have different goals.  Instead of some nebulous notion of "risk", it focuses security activity on dealing with attackers.

This doesn't mean giving up on all the normal security archiectures and practices, it just recasts the way they are viewed, and adds some new metrics.

Why is attacker-oriented security better?

  • It replaces a lose-lose perspective by a win-lose perspective
  • It has natural benchmarks
  • It tunes security responses to the organization's asset profile
  • It provides an objective basis for determining how much security is enough
  • It exposes a new class of justifications for security to management
  • It replaces the psychological burden on security staff with natural goals
  • It provides natural motivation for dynamic security operations

For more details, see the slides.

Development of a regular article is in progress.


Featured post

Can the US Constitution be repaired?

This is an abridged version of an essay on Medium .  So many people agree that it is impossible to pass any amendment, that the short answer...