workshop private

← all creations

Bind

games · created 2026-09-30

A lock has no partial credit — five pins at ten depths is 79,666 legal keys and 79,665 of them do exactly as well as a stick. Then the factory drills the chambers a thousandth of an inch out of line, one pin takes the whole load, and 39,833 median guesses collapse into about fifty moves. Tighten the shear line to stop that and the key fails first, because the key has to land all five at once and the pick lands them one at a time.

simulationcanvasgame-feelalgorithms

A pin tumbler cylinder, a tension wrench and one pick. Hold tension, find the pin that is carrying the plug, push it until it lets go, do it again. Five pins, maybe six, and the only thing standing between you and the door is that a lock is supposed to be a single hundred-thousand-way decision and is in practice five ten-way decisions in a row.

The reason it is five in a row rather than one is a manufacturing defect, and the defect is the whole game.

The collapse

A lock is a password check with no timing side channel — by design. Turn the wrong key and the plug does not move a millimetre more than it would with no key at all. There is no “four of your five cuts were right.” That is the entire security model, and on paper it is excellent:

lockpinsdepthsbittingsMACS-legalprobes to pickpushesseconds
Builder’s grade5716,80710,48320.29.07.5
Residential deadbolt510100,00079,66638.615.78.2
Commercial cylinder6101,000,000753,75492.629.916.2
The perfect lock510100,00079,666——never

The deadbolt’s keyway admits 79,666 keys once you remove the ones that violate the adjacent-cut rule. A blind search finds the right one after 39,833 on the median. Picking it takes 35.3 probes and 14.7 pushes — a factor of 797, and the factor is not the interesting part. The interesting part is that nothing about the lock changed. Same pins, same depths, same 16.3 bits of key. It just answered one pin at a time.

It answers one at a time because under torque the plug rotates a few microns until something stops it, and the something is whichever chamber was drilled closest to the line. That pin carries the entire load. The other four are springs. Push the loaded one to the shear line and the plug rotates a hair further, its shoulder slides under the driver pin, and the pin stays there — the lock is now remembering that you got it right. Then the next-closest chamber takes the load.

That is partial credit, delivered by the mechanism, in hardware, for free.

The defect the whole attack runs on

Turn off the defect and the attack stops existing. Here is the same deadbolt with the chamber position error swept from two thousandths of an inch down to nothing:

chamber σin thoumedian gap after a setchambers too tight to holdpickedseconds
0 µm0.00.0 µm100%0%—
4 µm0.21.8 µm91%57%13.4
8 µm0.33.6 µm64%73%10.2
15 µm0.66.7 µm39%81%8.3
23 µm0.910.2 µm29%88%7.9
33 µm1.314.7 µm21%91%7.4
50 µm2.022.3 µm18%95%7.0

At the bottom row the chambers are sloppy by two thousandths and the lock falls over in seven seconds. At the top row they are exact, every pin binds at the same instant, no pin is ever alone, and there is nothing for the plug’s shoulder to catch on — a set has zero rotation behind it, so the driver falls straight back down. That lock is in the demo. You can pick at it for as long as you like.

The middle column is why: the gap is how far the plug turns after a pin sets, and it is the width of the shoulder the driver has to land on. It is not a separate quantity from the tolerance. It is the tolerance, measured after the fact. A quarter of a thousandth of drilling error is a 1.8 µm ledge, which is still enough — 57% — and it is hard to overstate how small that is. The pick is not exploiting sloppiness. It is exploiting the last surviving trace of it.

The window is the same window

So close the shear line instead. The window is the vertical slop a pin’s boundary is allowed to have and still let the plug turn. Squeeze it and the pick has a smaller target. It also has a smaller key:

windowµm± thouone cut landsfresh key opensworn key openspickedseconds
6%23±0.534.7%0.5%0.0%0%—
10%38±0.855.5%5.3%0.3%6%6.3
16%61±1.277.6%28.1%3.2%59%6.5
22%84±1.790.5%60.8%11.4%67%7.3
28%107±2.196.7%84.4%26.0%73%7.9
34%130±2.699.0%95.1%43.9%76%8.8
42%160±3.199.9%99.3%67.3%79%9.4
50%191±3.8100.0%99.9%83.8%79%9.4

“Window” is stated as a fraction of one depth step, because it cannot go past half a step without two adjacent depths opening the same lock. “Fresh key” is cut to ±0.001”; “worn key” is the same key after a few years in a pocket.

Read the 16% row. The key’s individual cuts are landing 77.6% of the time, which sounds survivable, and the key opens the lock 28.1% of the time, which is not — because the key is a product and has to land all five at once. The pick, on the same row, is at 59%, because the pick is a sum and lands them one at a time, approaching each one slowly with feedback.

That is the whole defensive problem in one line. Tightening the shear line is the obvious counter to picking and it costs the defender a fifth power while costing the attacker a first. The window cannot be closed on the picker without being closed on the key first, and the margin is not small: to get the fresh key above 99% you need ±2.6 thou, and at ±2.6 thou the pick is at 76%.

Which is also why old locks pick easier. The “worn key” column is the same mechanism read the other way — every micron of wear the lock has to tolerate in its own key is a micron it hands to the pick, and it hands it permanently.

Tension, and the corridor between two failures

The wrench is the only continuous control in the game and it has to satisfy two contradictory requirements at once.

tension on the wrenchBuilder’s gradeResidential deadboltCommercial cylinderThe perfect lock
0.15, held there0%0%0%0%
0.22, held there7%1%0%0%
0.30, held there49%25%0%0%
0.38, held there70%55%17%0%
0.45, held there81%0%0%0%
0.55, held there86%0%0%0%
0.80, held there92%0%0%0%
0.95, held there92%0%0%0%
0.48, ducking to 0.34 for a groove84%69%27%0%
0.82, ducking to 0.34 for a groove92%82%63%0%

Too light and the shoulder cannot hold a driver against its spring, so every pin you set falls back out — and the narrower the ledge, the more wrench it takes to keep a driver on it, which means a well-made cylinder demands a firm hand. Too heavy and the pin you are pushing surges when the load finally comes off it, carrying the key pin up past the shear line and into the shell, where it jams the plug until the wrench goes slack and you lose everything.

Look at the two columns on the right. The builder’s lock has a wide corridor and gets easier the harder you pull, all the way to the stop. The deadbolt has spools in it, and any tension above 0.40 wedges the plug’s shoulder inside a spool’s waist so hard the pin will not pass — so the corridor is 0.30 to 0.40, ten percent wide, and a hand that cannot hold a tenth cannot pick the lock at all.

The last two rows are the escape, and it is the only one: pick at whatever the lock needs to hold its sets, and duck under for the two hundred milliseconds it takes to push a groove through. A set does not fall off its shoulder the instant the wrench goes light — the driver has to physically drop and the plug has to give the ground back, which takes long enough to dip under deliberately and not long enough to be careless in. 0.82 with a duck picks 63% of the commercial cylinders. 0.82 held flat picks none of them.

The tell

To duck at the right moment you have to know a groove from a shear line, and the obvious discriminator is the wrong one.

what moved the plugsamplesmedian °mean °µm of arc
a pin actually reaching the shear line26,0000.0800.1169
a serration taking the shoulder12,0000.9170.917102
a spool groove taking the shoulder8,0002.7502.750305

Solving a pin correctly turns the plug by nine microns. A spool’s waist swallowing the shoulder turns it by three hundred. The counterfeit pays 34× what the truth pays, and it pays it immediately, and everything else on the lock goes quiet at the same moment because the plug has rolled past the other chambers. A false set on the last pin of a deadbolt is a third of a degree of rotation, four pins showing green, and the distinct feeling of having just won.

So the size of the reward is not the signal. What is:

spoolsducks when the pin holds onsecondsfalse setsducks when it turned a lotnever ducks
090%7.80.072%75%
185%8.22.414%0%
279%8.55.40%0%
377%9.37.60%0%
472%9.810.70%0%
565%10.114.40%0%

One spool takes a picker who never ducks from 75% to zero, and takes a picker who ducks on a large rotation from 72% to 14% — because the large rotation only shows up when the spool happens to bind last, and it binds last one time in five. The picker who asks a different question — is the pin still carrying the plug? — goes from 90% to 85%, and five spools only take that to 65%.

A spool does not make the key space bigger. It does not make the window tighter. It costs you five points of success and three seconds, and in exchange it makes the lock’s feedback lie, which is worth everything against an attacker who is reading the wrong channel and nearly nothing against one who is not. That is a real and somewhat uncomfortable thing to know about security pins, and it is also exactly the trade every deception defence makes.

Seven ways to hold a lock open

policyBuilder’s gradeResidential deadboltCommercial cylinderThe perfect lockoversetsresets
work the wrench93% · 7.5s77% · 8.2s49% · 16.2s0%5.76.2
one tension, and the tell83% · 6.1s65% · 6.3s25% · 9.1s0%8.18.7
judge it by how far it turned78% · 6.0s0%0%0%8.513.0
trust every click83% · 6.1s0%0%0%6.211.4
feather it23% · 6.2s8% · 6.7s0%0%4.88.1
lean on it93% · 8.5s78% · 8.6s57% · 11.8s0%5.05.5
impatient100% · 7.5s76% · 8.5s33% · 14.9s0%2.62.6

Every policy reads only what a picker can sense: how each pin feels under the pick, whether it stayed up when released, and how far the plug turned. None of them sees the bitting, the binding order, or which pins are set. work the wrench starts at 0.46, ducks to 0.34 when a pin it just “set” is still carrying the plug, and permanently firms up by 0.07 every time a set it had banked comes back — it is trying to find this particular lock’s corridor by being wrong about it. lean on it skips all of that and just pulls at 0.82 with the same duck, and does about as well, more slowly. impatient gives up on a stuck push after a second and moves on, and it has the fewest oversets of anything on the list because the surest way to drive a key pin into the shell is to keep leaning on a pin that has already done everything it is going to do.

The two zeros in the middle are the ones worth looking at. Both of those pickers are competent; both are reading the feedback the lock offers most loudly; and both are at zero against two spools that cost the manufacturer a few cents.

What the model is, and what it is not

src/lock.mjs is headless and framework-free. Everything is microns, and plug rotation is also microns — arc at the plug surface — because a chamber drilled a thousandth out of line is a thousandth of arc, and the two quantities have to meet somewhere.

The geometry is real where it is cheap to be real. The 1/2” plug, Schlage’s 0.015” depth increment and MACS of 7, Kwikset’s 0.023” and MACS of 4, the ten depths, the adjacent-cut counting — those are the actual numbers, and the 16,807 → 10,483 and 100,000 → 79,666 reductions fall straight out of them rather than being asserted.

The picking is a calibrated caricature. A real pin stack has friction, inertia, a spring with a rate, a key pin that can tilt in its chamber, and a driver whose bottom edge is chamfered in a way that matters enormously. This has one number for how fast a pinched pin moves, one for how fast a free one does, and one — the surge when the load comes off — standing in for the whole reason heavy tension oversets. The spool dimensions are in the right range rather than measured off a part. The three thresholds the game is built on (0.18 to hold anything at all, 0.30 to hold a set on a nominal shoulder, 0.40 before a groove wedges) are tuned, not derived, and they are what make the corridor exist.

What is not tuned, and is the reason any of this was worth building, is the relationship in the third table. Both columns come from the same window and the same arithmetic — the key succeeds five times independently or not at all, the pick succeeds once at a time — and the fifth power is in there whether anybody wanted it or not.

Two honest caveats about the perfect lock. First, single-pin picking is not the only attack: a zero-tolerance cylinder is still open to raking, to combs, to impressioning, and to attacks that ignore the pins entirely, and the demo models none of those. Second, chamber position is not the only slop in a real cylinder — pin diameters vary, springs vary, the plug is not perfectly round — so a real lock built to zero chamber error would still produce a binding order from somewhere. The perfect lock is a thing you can build in a simulation to see what the defect was doing, not a product anyone has shipped.

Playing it

Hold space (or the pad on the left) for tension. It is a pedal, not a switch: it winds on while you hold and bleeds when you stop, slowly enough that ducking under a groove and coming back up is a move you can actually make.

Hold ↑ to push the pin under the pick. ← →, the number keys, or tapping a pin picks which one. R re-racks the same cylinder, N cuts a new one.

The loop:

  1. Get tension into the green band and leave it.
  2. Push each pin briefly. Four of them will move freely and drop back. One will be stiff and stay where you put it. That is the one.
  3. Push it until it clicks. Then stop pushing. The strip says SET; keep leaning and it will say OVERSET, and the only cure for that is letting the whole stack go.
  4. If the plug swings a long way and the pin is still stiff, that was a groove. Ease off the wrench — watch the plug turn back — and keep pushing the same pin. It will pass.
  5. If a pin you had set comes back, the wrench was too light for this cylinder’s shoulders. The bar remembers where you lost it and marks the spot.

Then try the perfect lock and notice how quickly the loop stops meaning anything.

Reuse

Everything in src/lock.mjs is microns, seconds and a tension in 0–1. No DOM, no canvas, no rendering.

node scripts/measure.mjs prints every table on this page; --csv gives one row per attempt. node scripts/screenshot-demo.mjs regenerates the thumbnail and the media shots by driving the demo’s own hooks in a real browser.

Gotchas

A note on the real thing

This is a simulation of a mechanism, not a technique. Nothing here transfers: there is no tactile channel, no wrench angle, no keyway to work around, and the three numbers the whole game balances on were chosen to make a corridor rather than measured off a cylinder. Single-pin picking is a hobby with clubs and competitions and a rule everyone repeats — your own locks, or locks you have permission to open, and never one that is in service on someone’s door.

The reason the mechanism is worth an afternoon is not the door. It is that a pin tumbler lock is the most physical version of a constant-time comparison anyone ever built, and it fails the same way string equality does when it returns on the first wrong byte: the search space was never the defence, the absence of partial credit was, and partial credit leaked out through a tolerance nobody could afford to close.