• MIKE (unregistered)

    Plot twist: the uint is a 32 bit representation of the PIN in either BCD, packed BCD, ASCII or EBCDIC.

  • JP (unregistered)

    In C, 0410 and 410 ARE numerically different values, likely on some other programming languages too :)

  • (nodebb)

    Semantically backwards, although the end point is valid.... It is not a PIN (which by definition is Numeric - hence the N), but rather it is a PII which is composed of digits....

    Addendum 2022-09-29 06:52: Additionally 0410 is equal to 264 is equal to 0x108 is equal to CCLXIV

    So any of those inputs should be accepted....(if it was truely a number)

  • RLB (unregistered) in reply to TheCPUWizard

    It is not a PIN (which by definition is Numeric - hence the N),

    Well, no. Because Dutch and German have two words: nummer/Nummer, which is a non-arithmetic number, and getal/Zahl, which is arithmetic. The distinction is almost, but not quite, the same as that between ordinal and cardinal numbers. Crucially, though, English does not have that distinction. And therefore, in English, you can have something which is a number, but is also not numeric.

  • Michael P (unregistered)

    Obligatory: TRWTF is what "via behind a PIN" means.

    I agree with the earlier comment that if leading zeroes are significant, it's a numeric passcode rather than a PIN. But even then, one could just add 10**n to an n-digit code. A 31- or 32-bit integer is larger enough to hold up to 9-digit codes like that.

  • NotAThingThatHappens (unregistered) in reply to RLB

    As a Dutchman, I approve of this message.

    Another titbit: English/American, the expression "You have my digits?" means "Do you have my phonenumber? (which is commonly numeric) and not "Do you have my fingers".

  • Hanzito (unregistered)

    If you enforce that the user enters 4 digits, then 410 simply won't occur. Still a weird type, though. Perhaps someone replaced char[4] by uint32, because the first one is a pointer in calls? That's one way to C it, at least.

  • COB666 (unregistered)

    Perhaps there is some hidden logic that left pads the number with '0's out to a 4 character string, so if the user enters 410, it will still try to validate against 0410.

  • Sauron (unregistered)

    Technically, there could even be additional layers of WTF on top of this.

    For example the PIN check could have been made between a text-typed input with the stored integer by using the implicit type coercion of some programming languages: http://phpsadness.com/sad/47

    Also, a 4-character PIN is one thing, but if there could be some nice additional WTFs when comparing very large numbers with overflows, losses of precision, etc.

    Comparison is quite a minefield of a topic.

  • Stella (unregistered)

    If a pin is numeric, I'm interested in the average value.

  • Alexey (unregistered)

    Sorry but WTF with this article? I think there's absolutely nothing wrong with PIN being uint. As long as we agree on the PIN length, 410 would mean 0410, no ambiguities here. (And if we decided to store different-length PINS in our database we would be crazy). So uint is perfectly fine. But char[4] is not - this is the root of all evil, because that's where PINS={'0410', ' 410', 'XXXX', 'NOTP'} come from.

  • dpm (unregistered) in reply to Hanzito

    That's one way to C it, at least.

    I hate you.

  • Barry Margolin (github)

    Is this actually a WTF? If the user enters 0410 into the device, and it parses it as a number, it will match 410 correctly.

    Does the device allow you to type less than 4 digits, and do they require that 410 be treated differently from 0410? That would indeed be a problem.

  • Sole Purpose Of Visit (unregistered) in reply to Barry Margolin

    Yes it is. Because the type PIN does not correspond to the type uint. Nor does it correspond to the type string.

    Let's rename the type PurpleMonkeyDishwasher. That removes any assumed numerical or other semantics, falsely based on the name.

    Now, you can store and retrieve a PurpleMonkeyDishwasher using any backing field you like (I would suggest a string, obviously), but you can only store to the backing field if the semantics of the input are correct. Which in this case would logically be validated via a regexp.

    The getter here clearly elides perfectly valid PurpleMonkeyDishwashers ... so, it's borked.

  • (nodebb) in reply to NotAThingThatHappens

    and not "Do you have my fingers".

    Unless you have just been involved in an industrial accident, in which case the question may be ambiguous.

  • Dave (unregistered) in reply to RLB

    "in English, you can have something which is a number, but is also not numeric."

    All languages have that - in English, sixty-one is an example.

    If you meant the other way around, a string made up of numerals is not a number in English, though the word is often abused. We really ought to say pi code, telephone code, etc.

  • MaxiTB (unregistered)

    I'm confused, the N in PIN standard for number, so yes, 0123 is the same as is 123.

    The reason is simple, leading zeros are just that, a formatting choice. In a set of digits [0..9] there is no other digit that could replace the 0 without changing the value of 123. So uint is the second best choice, after int.

  • DaveD (unregistered)

    Who would ever start their PIN with a 0? Don't do that! Slap! Slap! Whap!

  • A. N. Ominous (unregistered) in reply to MaxiTB

    0123 and 123 are not the same. This is open to interpretation.

    Simple example: 017 vs 17. By many conventions 017 is Octal 17; or base 8. 017 = octal 17 = 8 + 7 = 15.

    To use your example, 0123: 0123 = octal 123 = 8 squared + (2 x 8) + 3 = 64 +16 + 3 = 83.

    This can be enormously problematic when referring to IPv4 addresses in dotted-quad notation.

  • Toby Flanderson (unregistered)

    I had huge arguments with my colleagues years ago about how to store a CPF (brazilian SSN). It is a 11 character numeric string. Some of my coworkers wanted to store them as a numeric type. I argued that it would add more complexity, since the application would have to fill the leading zeroes, among other things.

  • Chris (unregistered)

    This "just works" only if you're restricted to a set number of digits, and you can rely on the calling code ensuring the correct number of digits have been entered. This makes it a poor choice and rather flaky.

    If you think of the PIN as a sequence of digits, rather than a single number, you'll likely end up with a much more stable implementation that can work with any changes to the requirements (or at least, with very little effort in the future). E.g. if the PIN is allowed to contain letters or other symbols (OK, no longer a number, but still a "PIN" for all intensive porpoises - I have no time for pedants), or use a variable number of digits (where 0123 is not the same as 00123).

  • NotAThingThatHappens (unregistered) in reply to Jeremy Pereira

    "Call me when you find me, do you..." DOH !

  • Ann on a Mouse (unregistered) in reply to Sole Purpose Of Visit

    It would depend on what a PIN actually is in practice on this device. Every bank account I’ve ever had with a PIN has had it as a 4-digit sequence, which EFFECTIVELY means an integer from 0 to 9999 — the sequence "0410" converts to 410 for storage, but when retrieved it gets formatted back to "0410". There’s no data loss and the conversions are simple: parse to integer to store, pad to 4 digits (and optionally read off the digits 1 by 1) to retrieve. I challenge you to give even a single valid PIN under that scheme which does not store as a unique value as an unsigned integer, or for which the stored unsigned integer value does not seamlessly convert back into the original PIN. There is only a practical difference between "0410" and 410 if the pin is really a password, not a PIN — in which case one of the issues involved is that the people who wrote the documentation don’t know what a PIN is.

  • Tina (unregistered)

    "Tina" here. I have never actually seen the particular UI, however, in other places on that device, other PINs are variable-length. FWIW, I believe my bank allows you to increas e the PIN length ...

  • Industrial Automation Engineer (unregistered) in reply to Ann on a Mouse

    Challenge accepted.

    My bank gave the option to switch from a four-digit PIN to an (optional) 5-digit pin. Lazy as I am, I went from 1234 to 01234. Now, if a hacker would enter 1234 (which is also still a valid PIN), it would validate erronously.

    Sidenote: you should not store a PIN. You should store the hash of that PIN. that's TRWTF

  • MaxiTB (unregistered) in reply to A. N. Ominous

    I am not sure what your are talking about, I was talking about numbers not how some language (like C, C++) represent numeric literals. So even if you consider that jump off-topic, the code is clearly C# and there is no leading 0 for octal numeric literals.

  • Sole Purpose Of Visit (unregistered) in reply to Ann on a Mouse


    But I think I would rather rely on correct typing and persistence, rather than "it's what the documentation says."

  • Sole Purpose Of Visit (unregistered) in reply to Industrial Automation Engineer

    Sidenote to sidenote:

    I like that thinking, and I agree. But it doesn't go far enough.

    The first problem I see is that, if the requirement "store PIN as a hash" is sent to a C# programmer (eg me), the first implementation is almost bound to be GetHash(). Which ... I suppose you could override it, but it's likely to be wrong, because collisions.

    The second problem is that you probably want to salt the hash somehow. At which point we get into basic cryptography, a field in which I am supremely ignorant. (One amongst many.)

    Then again, overriding GetHash() for our specific type, PurpleMonkeyDishwasher, is probably secure enough. So long as the attacker doesn't have access to the C# on the server (in which case they would be able to disassemble the algorithm used), they're no better off at guessing the hashing mechanism.

  • MaxiTB (unregistered) in reply to Sole Purpose Of Visit

    In C# you would use one of the Hash-Providers which are part of the framework since 1.0, like SHA256 ;-) And yes, you should always salt hashes, unsalted once are easily brute forced, especially when you have only 10,000 different results.

  • (nodebb) in reply to Ann on a Mouse

    Ann on a Mouse (unregistered) wrote "It would depend on what a PIN actually is in practice on this device. Every bank account I’ve ever had with a PIN has had it as a 4-digit sequence, which EFFECTIVELY means an integer from 0 to 9999"

    You can't be blamed for thinking that, because banks are absolutely TERRIBLE about allowing only 4 digits, but PINs are by standard 4 - 12 digits long, and leading zeroes are absolutely significant. I've been out of the business for a long time so I may have the wrong standard, but I believe this is be covered in ISO 9564/ANSI X9.8.

  • (nodebb) in reply to RLB

    Good point & interesting observation, but you swapped the definitions/their meanings in your explanation. "nummer/Nummer" denotes an index in a sequence (123 could be the 321th number), whereas "getal/Zahl" refers to the number in isolation (wherever 123 appears in some sequence, it's still the number 123). The main problem of this CODESOD is that "cijfer/Ziffer" is interpreted numerically instead of just taking it for what it is, namely some glyph (which has a unicode/ASCII/... number :-).

  • Ann on a Mouse (unregistered) in reply to Bim Zively
    Comment held for moderation.
  • (nodebb) in reply to MIKE

    Plot twist: the uint is a 32 bit representation of the PIN in either BCD, packed BCD, ASCII or EBCDIC. Something like that. Based on real-world experience with a relatively popular device which accepts PINs for authentication, it is probably Hex encoding, where zero is replaced with an "A", and PINs can be any length between 1 and 8 "digits". So a "PIN" of "01234" would be 0xa1234. Byte order would be compiler dependent but probably Big Endian, as the bit of hardware was written in some sort of 8 bit assembly language, or the original "architect" just didn't like arrays.

    Addendum 2022-10-03 14:44:

    I dislike this forum software, how it handles quotes and it's lack of a preview feature.

    Also, why can I only describe my desired revision through a tiny slit in the browser?

  • Raul (unregistered)

    Are they guaranteed to always be 4 digit numerical passwords (crucially not "numbers", because then 0410 and 410 should in fact be considered the same thing) though? It's often the case with these. And then it's honestly FINE. It's a bit hacky and might cause trouble down the line, but it's FINE. You won't have a collision on 0410 vs 410, because 410 by itself is simply not an option, and neither is any other sub-4 digit code, so using them to represent codes with leading zeroes is FINE.

Leave a comment on “The Misleading PIN”

Log In or post as a guest

Replying to comment #:

« Return to Article