{"id":16793557,"url":"https://github.com/mdp/dotp","last_synced_at":"2025-08-23T03:45:36.267Z","repository":{"id":66279371,"uuid":"49328789","full_name":"mdp/dotp","owner":"mdp","description":"Decentralized One Time Passwords","archived":false,"fork":false,"pushed_at":"2022-12-11T10:23:51.000Z","size":3257,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-11T00:01:53.419Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mdp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-01-09T15:10:20.000Z","updated_at":"2023-08-23T20:44:08.000Z","dependencies_parsed_at":null,"dependency_job_id":"bd248845-7416-4757-8222-d935ecce8345","html_url":"https://github.com/mdp/dotp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mdp/dotp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdp%2Fdotp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdp%2Fdotp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdp%2Fdotp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdp%2Fdotp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mdp","download_url":"https://codeload.github.com/mdp/dotp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdp%2Fdotp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271739902,"owners_count":24812636,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-23T02:00:09.327Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-13T08:49:38.597Z","updated_at":"2025-08-23T03:45:36.223Z","avatar_url":"https://github.com/mdp.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dOTP\n##decentralized One Time Passwords\n\n__WARNING__\n\nThis code has not been audited or vetted in any way.\nI make no guarantees about its security or safety.\nThis is more of a prototype than a fully baked two factor authentication system.\n\n### Details\n\nBased on the LibSodium(NaCL) encryption library, dOTP uses public key encryption to build a challenge and response system for creating One Time Passwords (OTP)\n\n[Android Beta](https://play.google.com/apps/testing/space.atrailing.dauth)\n\nAndroid/iOS Client Source Code [mdp/dAuth](https://github.com/mdp/dAuth)\n\n#### Design goals\n\n1. Should be completely decentralized. No third parties involved.\n  - There are plenty of services that provide a second factor authentication solution. These typically\n  are not free and fail if the third party goes down or is compromised.\n2. Should rely on public key encryption rather than symmetric\n  - The current open standard for OTP relies on a shared key. This means that both the client and the server must keep this key secret. dOTP means you can safely store a users public key in a database without fear that it's exposure will compromise your security or the security of your users.\n  - Shared keys means that each client must use a different key for each service. dOTP allows users to share their public key with as many services as they like.\n3. Should work on mobile\n  - U2F is typically implemented as a hardware USB token, which makes it difficult to use with a mobile device (especially iOS)\n4. Should work completely offline\n  - You should be able to airgap your mobile authentication device or autheticate when internet is not avaiable.\n5. Is usable as a single factor authentication and as an identity\n  - U2F must always be paired with an identity. dOTP is in and of itself an identity. (There are pros and cons to this)\n\n### Example use for SSH Two Factor\n\nSetup: This assumes that we have the [dotp CLI](https://github.com/mdp/go-dotp) installed on the server and SSH setup for enforcing two factor.\n\nFrom our terminal it looks like this:\n\n![Terminal two factor](https://github.com/mdp/dotp/raw/master/sshTwoFactor1.gif)\n\nAnd using the iOS app looks like this:\n\n![iOS app](https://github.com/mdp/dotp/raw/master/dAuthDemo1.gif)\n\n\n#### Basic steps to using dOTP\n\n1. Launch the mobile app and create a new keypair if you don't already have one.\n2. Export your public key and give it to the authenticating server (Can be [scanned via your laptops webcam](https://mdp.github.io/dotp/scan/?redir=https%3A%2F%2Fmdp.github.io%2Fdotp%2Fdemo%2F%23%2F%3F))\n3. When logging into the authentication server, the server will encode a One Time Password and encrypt with the users public key. A QR Code will then be displayed for the user to scan with their mobile app. [Example](https://mdp.github.io/dotp/demo/#/BPAkh9cmVnQYwJN5QCmoysNp89355PfNyDfApBWmuMQZL?_k=6y3749)\n4. The mobile app will decrypt the message using public keys matching secret and display the One Time Password along with the name/hostname of the authenticating server\n5. The user will login using the displayed password if the name/hostname matches\n\n#### Encoding a Challenge into a QRCode\n\nChallenges are meant to be encoded as a QR Code and scanned by the authenticating user. They have the following format (Value[byte size]):\n\nBase58Encode(Version[1]|PublicKeyFirstByte[1]|SealedBox[...])\n\nBroken down:\n\n- Version: Currently at 0, allows the challenge protocol to change as needed\n- PublicKeyFirstByte: Lets the client narrow down keys to attempt, but doesn't give away the authenticators public key\n- SealedBox: the libsodium encoded result for `crypto_box_seal`\n\nIn JavaScript it looks like this:\n\n```javascript\nfunction(recPubKeyFirstByte, challengerPub, box) {\n  var challenge = new Uint8Array(1+1+box.length)\n  challenge[0] = VERSION\n  challenge[1] = recPubKeyFirstByte\n  challenge.set(box, 2)\n  return Base58.encode(challenge)\n}\n```\n\n#### Cryptography behind dOTP\n\nThe basics are as follows:\n- Libsodium [crypto_box_seal](https://download.libsodium.org/doc/public-key_cryptography/sealed_boxes.html) function used to encrypt the name of the challenger and the OTP, passed the following values\n  - The \"ChallengerName|OTP\" we are encrypting for the recipient/authenticator. eg. \"https://github.com|12345678\"\n  - Public Key of the recipient/authenticator\n\n`Sodium.crypto_box_seal(otp, publicKey[32 bytes])`\n\n__dOTP assumes that the QRCode is displayed via a secure channel (HTTPS/SSH)__\n\nThe Challenge QRCode does not prove that the service displaying the QRCode is the same service that created it. The end user must make sure that they are authenticating over a secure channel, and that the challenger name (eg my.ssh.host.com) matches where the challenge code is being displayed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdp%2Fdotp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmdp%2Fdotp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdp%2Fdotp/lists"}