Out of the following operating systems, which one do you use the most, not at work, but in your free personal time?
Please consider boosting for a larger sample size. Thank you.
#poll #os #computing #fediverse
Reading NFC Passport Chips in Linux
https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/
For boring and totally not nefarious reasons, I want to read all the data contained in my passport's NFC chip using Linux. After a long and annoying search, I settled on roeften's pypassport.
I can now read all the passport information, including biometrics.
Table of Contents
BackgroundBackground
The NFC chip in a passport is protected by a password. The password is printed on the inside of the physical passport. As well as needing to be physically close to the passport for NFC to work0, you also need to be able to see the password. The password is printed in the "Machine Readable Zone" (MRZ) - which is why some border guards will swipe your passport through a reader before scanning the chip; they need the password and don't want to type it in.
I had a small problem though. I'm using my old passport1 which has been cancelled. Cancelling isn't just about revoking the document. It is also physically altered:
Cut off the bottom left hand corner of the personal details page, making sure you cut the MRZ on the corner opposite the photo.
So a chunk of the MRZ is missing! Oh no! Whatever can we do!?
Recreating the MRZ
The password is made up of three pieces of data:
Passport Number (Letters and Numbers)
Date of Birth (YYMMDD)
Expiry Date (YYMMDD)
Each piece also has a checksum. This calculation is defined in Appendix A to Part 3 of Document 9303.
Oh, and there's a checksum for the entire string. It's this final checksum which is cut off when the passport cover is snipped.
The final password is: Number Number-checksum DOB DOB-checksum Expiry Expiry-checkum checksum-of-previous-digits
Python code to generate an MRZ
If you know the passport number, date of birth, and expiry date, you can generate your own Machine Readable Zone - this acts as the password for the NFC chip.
def calculateChecksum( value ): weighting = [7,3,1] characterWeight = { '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '<': 0, 'A':10, 'B':11, 'C':12, 'D':13, 'E':14, 'F':15, 'G':16, 'H':17, 'I':18, 'J':19, 'K':20, 'L':21, 'M':22, 'N':23, 'O':24, 'P':25, 'Q':26, 'R':27, 'S':28, 'T':29, 'U':30, 'V':31, 'W':32, 'X':33, 'Y':34, 'Z':35 } counter = 0 result = 0 for x in value: result += characterWeight[str(x)] * weighting[counter%3] counter += 1 return str(result%10)def calculateMRZ( passportNumber, DOB, expiry ): """ DOB and expiry are formatted as YYMMDD """ passportCheck = calculateChecksum( passportNumber ) DOBCheck = calculateChecksum( DOB ) expiryCheck = calculateChecksum( expiry ) mrzNumber = passportNumber + passportCheck + DOB + DOBCheck + expiry + expiryCheck mrzCheck = calculateChecksum( mrzNumber ).zfill(2) mrz = passportNumber + passportCheck + "XXX" + DOB + DOBCheck + "X" + expiry + expiryCheck + "<<<<<<<<<<<<<<" + mrzCheck return mrzprint( calculateMRZ("123456789", "841213", "220229") )
Can you read a cancelled passport?
I would have thought that cutting the cover of the passport would destroy the antenna inside it. But, going back to the UK guidance:
You must not cut the back cover on the ePassport
Ah! That's where the NFC chip is. I presume this is so that cancelled passports can still be verified for authenticity.
Cryptography and other security
The security is, thankfully, all fairly standard Public Key Cryptography - 9303 part 11 explains it in excruciating levels of detail.
One thing I found curious - because the chip has no timer, it cannot know how often it is being read. You could bombard it with thousands of password attempts and not get locked out. Indeed, the specification says:
the success probability of the attacker is given by the time the attacker has access to the IC, the duration of a single attempt to guess the password, and the entropy of the passport.
Can you brute-force a passport?
Wellllll… maybeeeee…?
Passports are generally valid for only 10 years. So that's 36,525 possible expiry dates.
Passport holders are generally under 100 years old. So that's 3,652,500 possible dates of birth.
That's already 133,407,562,500 attempts - and we haven't even got on to the 1E24 possible passport numbers!
In my experiments, sending an incorrect but valid MRZ results in the chip returning "Security status not satisfied (0x6982)" in a very short space of time. Usually less than a second.
But sending that incorrect attempt seemed to introduce a delay in the next response - by a few seconds. Sending the correct MRZ seemed to reset this and let the chip be read instantly.
So, if you knew the target's passport number and birthday, brute forcing the expiry date would take a couple of days. Not instant, but not impossible.
Most commercial NFC chips support 100,000 writes with no limit for the number of reads. Some also have a 24 bit read counter which increments after every read attempt. After 16 million reads, the counter doesn't increment. It could be possible for a chip to self-destruct after a specific number of reads - but I've no evidence that passport chips do that.
Is it worth brute-forcing a password?
If you were to brute-force the MRZ, you would discover the passport-holder's date of birth. You would also get:
A digital copy of their photo,
Their full name,
Their sex2,
The country which issued their passport, and
Their nationality.
All of that is something which you can see from looking at the passport. So there's little value in attempting to read it electronically.
Installing
As mentioned, I'm using https://github.com/roeften/pypassport
The only library I needed to install was pyasn1 using pip3 install pyasn1 - your setup may vary.
Download PyPassport. In the same directory, you can create a test Python file to see if the passport can be read. Here's what it needs to contain:
from pypassport import epassport, reader# Replace this MRZ with the one from your passportMRZ = "1234567897XXX8412139X2202299<<<<<<<<<<<<<<04"def trace(name, msg): if name == "EPassport": print(name + ": " + msg)r = reader.ReaderManager().waitForCard()ep = epassport.EPassport(r, MRZ)ep.register(trace)ep.readPassport()
Plug in your NFC reader, place your passport on it, run the above code. If it works, it will spit out a lot of debug information, including all the data it can find on the passport.
Getting structured data
The structure of the passport data is a little convoluted. The specification puts data into different "Data Groups" - each with its own ID.
By running:
ep.keys()
You can see which Data Groups are available. In my case, ['60', '61', '75', '77']
60 is the common area which contains some metadata. Nothing interesting there.61 is DG1 - the full MRZ. This contains the holder's name, sex, nationality, etc.77 is the Document Security Object - this was empty for me.75 is DG2 to DG4 Biometric Templates - this contains the image and other metadata.
Dumping the biometrics - print( ep["75"] ) - gives these interesting pieces of metadata:
'83': '20190311201345','meta': { 'Expression': 'Unspecified', 'EyeColour' : 'Unspecified', 'FaceImageBlockLength': 19286, 'FaceImageType': 'Basic', 'FeatureMask': '000000', 'FeaturePoint': {0: {'FeaturePointCode': 'C1', 'FeatureType': '01', 'HorizontalPosition': 249, 'Reserved': '0000', 'VerticalPosition': 216}, 1: {'FeaturePointCode': 'C2', 'FeatureType': '01', 'HorizontalPosition': 141, 'Reserved': '0000', 'VerticalPosition': 214}}, 'Features': {}, 'Gender': 'Unspecified', 'HairColour': 'Unspecified', 'ImageColourSpace': 'RGB24', 'ImageDataType': 'JPEG', 'ImageDeviceType': 0, 'ImageHeight': 481, 'ImageQuality': 'Unspecified', 'ImageSourceType': 'Static Scan', 'ImageWidth': 385, 'LengthOfRecord': 19300, 'NumberOfFacialImages': 1, 'NumberOfFeaturePoint': 2, 'PoseAngle': '0600B5', 'PoseAngleUncertainty': '000000', 'VersionNumber': b'010' }
If I understand the testing document - the "Feature Points" are the middle of the eyes. Interesting to see that gender (not sex!) and hair colour are also able to be recorded. The "PoseAngle" represents the pitch, yaw, and roll of the face.
Saving the image
Passport images are saved either with JPEG or with JPEG2000 encoding. Given the extremely limited memory available photos are small and highly compressed. Mine was a mere 19KB.
To save the image, grab the bytes and plonk them onto disk:
photo = ep["75"]["A1"]["5F2E"]with open( "photo.jpg", "wb" ) as f: f.write( photo )
As expected, the "FeaturePoints" co-ordinates corresponded roughly to the centre of my eyes. Nifty!
What didn't work
I tried a few different tools. Listed here so you don't make the same mistakes as me!
mrtdreader
The venerable mrtdreader. My NFC device beeped, then mrtdreader said "No NFC device found."
I think this is because NFC Tools haven't been updated in ages.
Jean-Francois Houzard's and Olivier Roger's pyPassport
I looked at pyPassport but it is only available for Python 2.
beaujean's pyPassport
This pypassport only checks if a passport is resistant to specific security vulnerabilities.
d-Logic
Digital Logic's ePassport software only works with their hardware readers.
Android reader
tananaev's passport-reader - works perfectly on Android. So I knew my passport chip was readable - but the app won't run on Linux.
Is it worth it?
Yeah, I reckon so! Realistically, you aren't going to be able to crack the MRZ to read someone's passport. But if you need to gather personal information3, it's perfectly possible to do so quickly from a passport.
The MRZ is a Machine Readable Zone - so it is fairly simple to OCR the text and then pass that to your NFC reader.
And even if the MRZ is gone, you can reconstruct it from the data printed on the passport.
Of course, this won't be able to detect fraudulent passports. It doesn't check against a database to see if it has been revoked4. I don't think it will detect any cryptographic anomalies.
But if you just want to see what's on your travel documents, it works perfectly.
There are some commercially available long range readers - up to 15cm! I've no doubt some clever engineer has made a some high-powered radio device which can read things from a mile away using a Pringle's tube. Of note, the ICAO guidance says:
the unencrypted communication between a contactless IC and a reader can be eavesdropped within a distance of several metres.
↩︎#activitypub #mitra #? @rf
Поднял минималистичный инстенс mitra - а mastodon с ним не хочет педерироваться, говорит 503, а курл нормально всё достаёт:
curl http://mitra.root.sx/users/l29ah --header 'Accept: application/activity+json'
ЧЯДНТ?
#slop
I must not delay; procrastination is the slow mind-killer that steals lives in five-minute chunks - I will begin the smallest possible step now, and where action has passed, only progress will remain.
About 1.5 years ago my friend was (falsely) accused of terrorism.
All of their electronic devices were seized, plus my stash of hard drives (stored at their place for reasons).
Of course police didn’t find any evidence. Culprit that impersonated my friend (and many others) got arrested recently (article in Polish).
Police returned the hardware few months ago and I found that all of my drives are now e-waste thanks to their carelessness, which made me (understandably) furious. I even considered suing them.
Said very good friend of mine entrusted me with their personal phone and pattern to unlock it. I charged and booted it for the first time since February 2024 and were curious how it was pwned. I knew police used cellebrite on it.
My crime is that of curiosity
As it turns out, police forgot to clean after themselves (there was an attempt) and left payloads, logs, and backdoor intact.
Took a peek at the first-stage payload but it’s too complex for me to reverse-engineer on my own. It’s relatively well obfuscated, but I can tell it’s using RNDIS (likely spawning a server?) and TLS-encrypted connection to talk to Cellebrite box.
If you’re a security researcher (or just curious nerd with more spoons than me) and you would like to take a look - here you go.
Payload was uploaded onto the device on 2024-02-21. If you want to re-create the environment it was executed on, you will need a:
Samsung Z Flip3 5G (SM-F711B)
Android build SP2A_220305.013.F711BXXS2CVHF
Rough execution flow:
1. USB device plugged in (Cellebrite Cheetah)
2. USB controller switches to host mode
3. Gadget switching USB VID/PID to load kernel modules (hid_steam, hid_apple, hid_prodikeys, hid_logitech_hidpp, hid_magicmouse, hid_aksys and tries to exploit quirks)
4. Module 'hid_aksys' leaks memory
5. Screen unlocked
6. ADB key '82:E5:EA:F3:DC:D1:7D:CA:65:3C:D4:58:65:CD:81:8E' added to trusted keys on the device
7. First-stage payload '/data/local/tmp/falcon' copied onto the device.
8. Second-stage payload (seemingly) executed as root:
- /data/local/tmp/chrome-command-line
- /data/local/tmp/android-webview-command-line
- /data/local/tmp/webview-command-line
- /data/local/tmp/content-shell-command-line
- /data/local/tmp/frida-server-16.1.4-android-arm64
- /data/local/tmp/init
9. Data extraction (photos, telegram, firefox, downloads)
Have fun!
When our first kid was born, I realized I was going to lose a lot of time doing... _nothing_ (baby napping somewhere, waiting for kid to come out of some activity...), so it'd be neat if I had a way to code from anywhere, without having to carry my laptop.
So I thought: can you make a keyboard you can use while standing, and that you can attach your phone to?
Didn't have time to fully go for it back then (having a small kid). But now I do!
Here's test 5. Still not soldered. Hopefully next one
#? @rf
Почему на посуде не маркируют её вес? Очень неудобно, что приходится самому этим заниматься, и самодельная маркировка куда менее устойчива к мытью и прочему износу, чем фабричные краски, штампы и литьевые выступы, которые и так применяются почти ко всей посуде.
#bitcoin @rf
https://github.com/jlopp/physical-bitcoin-attacks на случай важных переговоров
@shuro@friends.deko.cloud @grishka@friends.grishka.me при этом забавный факт - у нас в институте интернет воткнут выше тспу потому что часть трафика секретная, и кому не положено его досматривать нельзя. А кому положено в уставе ютупь блокировать не прописано. Ушлые коллеги открывают удаленный рабочий стол на рабочие машины и оттуда вынимают голосу свободы. Иноагенты проклятые. Учёных надо к ногтю прижать.
@rf
Мне нужно СРОЧНО до завтрашнего утра окончательно утвердить версию пустышки хама, помогите пожалуйста
Есть в общем две формулировки маленького серого уведомления с иконкой приложения внизу экрана:
1. Приложение не отвечает
2. При запуске приложения произошла ошибка
Еще есть открытие черного экрана вместе с этим серым уведомлением, можно сделать чтоб не открывалось, просто серая самоисчезающая табличка внизу
А так же, есть серое окно с надписью "Приложение MAX остановлено" и внизу "ОК" (скрин прилагается, цвет кнопки в цвет расцветки интерфейса телефона)
И вопрос стоит в том, как это все скомбинировать так, чтоб выглядело натурально. Типа, черный экран + табличка с иконкой внизу экрана + табличка с кнопкой ок, это вариант который сейчас (на скрине), оттуда можно выкинуть любой элемент или поменять надписи. Я слишком не шарю в этой теме чтоб самостоятельно оценить уровень реалистичности, нужно сделать вид типа устройство не поддерживает приложение, благо у меня ноунейм телефон
Колонка для второго номера “Фронды”
Только что сдала в редактуру статью для третьего номера “Фронды“. А коли так, почему бы не выложить в открытый доступ свою колонку из второго номера, посвящённого демократии. Вот, извольте:
Уроки свободы
Всем привет, с вами снова Анкап-тян, и сегодня мы поговорим об уроках, которые нам дарит такое общественное устройство, как демократия.
Урок решительности
Эллинская демократия началась с тираноубийства. С тех пор убийство тирана считается хорошим тоном и неплохой прелюдией к установлению более свободного политического строя. Большинство тиранов извлекли из этого урок, а потому стараются сохранять внешние атрибуты демократии. Извлечём урок и мы:
Самый прямой путь к установлению демократии – уничтожить тирана.. Уничтожение армии или экономики – гораздо более окольные и ненадёжные пути. Договариваться с тираном о его мирном уходе – ещё более ненадёжный путь.
Урок бдительности
Борясь за демократию, люди хотят не демократии как таковой. Они хотят свободы от тирании – то есть от режима, в котором к ним произвольно применяют насилие. Демократия – это лишь семейство различных компромиссных общественных устройств, призванных не допустить рецидива тирании. Общее во всех стабильных демократиях – принцип разделения власти. Вся власть – никому! Тирания народного собрания – точно такая же тирания, как тирания одного человека. Сформулируем наш урок следующим образом:
Конструируйте систему самоуправления так, чтобы в вашем сообществе такая система не давала никому узурпировать власть. Никакого расширительного толкования норм! Никаких чрезвычайных полномочий! Любой носитель власти – потенциальный тиран. Будьте бдительны!
Урок различения целей и средств
Координация в сообществе подразумевает работу по её обеспечению. Работу должен кто-то делать. Этого кого-то надо найти и привлечь к работе. Как искать? В современных демократиях всё обычно сводится к двум механизмам: должностное лицо либо назначается вышестоящим, либо выбирается голосованием. Голосование – это всего лишь одно из возможных средств достижения компромиссного решения по отбору из группы кандидатов, и у него масса минусов. Есть множество других средств. Исходно самым непредвзятым средством вообще считался жребий. Ещё есть экзамены и иные виды состязаний, есть покупка должностей, есть тендеры, есть волонтёрство… Демократия не сводится к голосованиям. Урок отсюда очевиден:
Не подменяйте цели средствами. Не пытайтесь использовать инструмент для всего подряд, даже если он очень модный. Используйте то, что проще, надёжнее, и что решает именно ту задачу, которая поставлена.
Урок выхода из порочного круга
Как ни распределяй власть, какие ни внедряй сдержки и противовесы, как ни связывай власть имущих законами, система со временем деградирует. Деградировав, она порождает новых тиранов, а потом по их головы приходят новые тираноборцы… Что может помешать соблазну сконцентрировать власть? Только одно: отсутствие того, что можно сконцентрировать.
Если координация происходит добровольно, в этом процессе нет места для того, кто принуждает. Чем больше места занимают добровольные отношения, тем меньше места занимают властные. Отсюда простой урок:
Если вам что-то нужно от других, спрашивайте, что хотят взамен. Не считайте, что вас должны обслужить даром. Если от вас что-то требуют, называйте свою цену. Не считайте, что вы должны обслуживать других даром. Согласны сотрудничать – сотрудничайте. Не согласны – не сотрудничайте. Всякий претендующий на власть должен понимать: принуждать людей себе дороже. Будут саботировать и искать удобного случая ударить исподтишка. Никому не хочется войти в историю в качестве свергнутого тирана.
Подведём итог
С одной стороны, демократия – это способ не дать немногим всю полноту власти над большинством. С другой стороны, демократия это возможность для большинства получить общественные блага дешевле, чем они бы стоили на рынке. Это большой соблазн, но надо отдавать себе отчёт в том, что это тоже тирания, только тирания большинства. Переход к рынку вместо принуждения – это нравственный выбор людей, которые сознательно отказываются быть тиранами. Только этот путь ведёт к настоящей свободе.
После 3 лет работы мои "умные" часы от Lenovo уже раза 2 или 3 выключаются, когда индикатор показывает наполовину заряженную батарею.
Решил попробовать заменить аккумулятор, разобрал - и обнаружил, что аккумуляторов именно с таким типоразмером (392121) нет в продаже нигде. АлиЭкспресс, маркетплейсы, Чип и Дип, сайты других магазинов компонентов - ни следа.
Больше того. Если я правильно понял логику обозначений, толщина аккумулятора 3,9 мм, а 2 других размера - по 21 мм. Так вот аккумуляторов, которые укладывались бы в эти цифры, тоже нет. Хоть один размер да вылезает. Где ещё поискать-то? Жалко выбрасывать часы, если проблема действительно только в батарейке.
@rf #smartwatch
#праздник #нумерология @rf
С днём работников СИЗО и тюрем!
cyberjunkie, transhumanist, code monkey, FOSS fanatic, embedded systems engineer, 3D printing zealot, ancap, garbage tinkerer, philosophical zombie, polyamorous postgender panromantic pornsexual