[{"data":1,"prerenderedAt":337},["ShallowReactive",2],{"navigation":3,"/blog/rsa-fips-fapi-myth":141,"/blog/rsa-fips-fapi-myth-surround":326},[4,36,55,80,101,116,128],{"title":5,"path":6,"stem":7,"children":8,"icon":35},"ASP.NET Core","/aspnet-core","1.aspnet-core/1.index",[9,11,15,19,23,27,31],{"title":10,"path":6,"stem":7},"Cursor Pagination",{"title":12,"path":13,"stem":14},"Dapper - Micro ORM","/aspnet-core/dapper","1.aspnet-core/2.dapper",{"title":16,"path":17,"stem":18},"DbUp - Database Migrations","/aspnet-core/dbup","1.aspnet-core/3.dbup",{"title":20,"path":21,"stem":22},"Serilog - Structured Logging for .NET","/aspnet-core/serilog","1.aspnet-core/4.serilog",{"title":24,"path":25,"stem":26},"Class Inheritance in C#","/aspnet-core/inheritance","1.aspnet-core/5.inheritance",{"title":28,"path":29,"stem":30},"C# Collections","/aspnet-core/collections","1.aspnet-core/6.collections",{"title":32,"path":33,"stem":34},".NET gitignore Command","/aspnet-core/gitignore","1.aspnet-core/7.gitignore",false,{"title":37,"path":38,"stem":39,"children":40,"icon":35},"Oauth2.0 and OpenIdConnect","/oauth2andopenidconnect","10.oauth2andopenidconnect/1.index",[41,43,47,51],{"title":42,"path":38,"stem":39},"RFC 6749 - OAuth 2.0 Authorization Framework",{"title":44,"path":45,"stem":46},"Authentication (AuthN) vs Authorization (AuthZ)","/oauth2andopenidconnect/authnandauthz","10.oauth2andopenidconnect/2.authnandauthz",{"title":48,"path":49,"stem":50},"TOTP Authentication","/oauth2andopenidconnect/totp","10.oauth2andopenidconnect/3.totp",{"title":52,"path":53,"stem":54},"OAuth 2.0 Resource Indicators - RFC 8707","/oauth2andopenidconnect/oauth2resourceindicators","10.oauth2andopenidconnect/4.OAuth2ResourceIndicators",{"title":56,"path":57,"stem":58,"children":59,"page":35},"Azure","/azure","2.azure",[60,64,68,72,76],{"title":61,"path":62,"stem":63},"Azure Cost Management","/azure/azuremanagementandgovernance","2.azure/1.Azuremanagementandgovernance",{"title":65,"path":66,"stem":67},"Azure Policy","/azure/azurepolicy","2.azure/2.azurepolicy",{"title":69,"path":70,"stem":71},"Code Blocks","/azure/code-blocks","2.azure/3.code-blocks",{"title":73,"path":74,"stem":75},"Prose Components","/azure/prose-components","2.azure/4.prose-components",{"title":77,"path":78,"stem":79},"Images and Embeds","/azure/images-embeds","2.azure/5.images-embeds",{"title":81,"path":82,"stem":83,"children":84,"page":35},"Git","/git","3.git",[85,89,93,97],{"title":86,"path":87,"stem":88},"Git Rebase","/git/git-rebase","3.git/1.git-rebase",{"title":90,"path":91,"stem":92},"Git Stash","/git/git-stash","3.git/2.git-stash",{"title":94,"path":95,"stem":96},"SemVer","/git/semver","3.git/3.semver",{"title":98,"path":99,"stem":100},"Conventional Commits","/git/conventional-commits","3.git/4.conventional-commits",{"title":102,"path":103,"stem":104,"children":105,"icon":35},"Design Patterns","/design-patterns","7.design-patterns/1.index",[106,108,112],{"title":107,"path":103,"stem":104},"Introduction",{"title":109,"path":110,"stem":111},"Installation","/design-patterns/installation","7.design-patterns/2.installation",{"title":113,"path":114,"stem":115},"Usage","/design-patterns/usage","7.design-patterns/3.usage",{"title":117,"path":118,"stem":119,"children":120,"icon":35},"Software Principles","/principles","8.principles/1.index",[121,122,125],{"title":107,"path":118,"stem":119},{"title":109,"path":123,"stem":124},"/principles/installation","8.principles/2.installation",{"title":113,"path":126,"stem":127},"/principles/usage","8.principles/3.usage",{"title":129,"path":130,"stem":131,"children":132,"icon":35},"Software Architecture","/architecture","9.architecture/1.index",[133,135,138],{"title":134,"path":130,"stem":131},"CQRS Pattern",{"title":109,"path":136,"stem":137},"/architecture/installation","9.architecture/2.installation",{"title":113,"path":139,"stem":140},"/architecture/usage","9.architecture/3.usage",{"id":142,"title":143,"body":144,"date":315,"description":316,"extension":317,"featured":35,"meta":318,"navigation":319,"path":320,"readTime":321,"seo":322,"stem":323,"tag":324,"__hash__":325},"blog/blog/5.rsa-fips-fapi-myth.md","RSA Isn't Banned by FIPS or FAPI — But the Way Most People Use It Basically Is",{"type":145,"value":146,"toc":304},"minimark",[147,156,161,171,174,178,204,212,216,219,228,231,235,238,245,249,252,255,259],[148,149,150,151,155],"p",{},"There's a common claim floating around security discussions that RSA has been dropped from FIPS and FAPI. It's a reasonable thing to believe, given how much scrutiny RSA's padding schemes have gotten lately — but it's not quite accurate, and the actual story is more useful than the myth. RSA is still an approved algorithm in both standards. What changed is ",[152,153,154],"em",{},"which version"," of RSA is allowed, and that distinction matters more than the headline claim does.",[157,158,160],"h2",{"id":159},"fips-still-approves-rsa-it-just-retired-its-weaker-cousins","FIPS Still Approves RSA — It Just Retired Its Weaker Cousins",[148,162,163,170],{},[164,165,169],"a",{"href":166,"rel":167},"https://csrc.nist.gov/pubs/fips/186-5/final",[168],"nofollow","FIPS 186-5",", NIST's Digital Signature Standard published in February 2023, specifies exactly three approved techniques for generating and verifying digital signatures: RSA, ECDSA (elliptic curve), and EdDSA (Edwards curve). RSA is right there, first on the list — it was never removed.",[148,172,173],{},"What actually happened in the 186-5 revision is narrower. DSA, the original NIST-designed signature algorithm, was dropped from approval for new signature generation — retained only to verify old signatures already created with it — due to a combination of low industry adoption and academic findings about vulnerabilities when domain parameters aren't generated correctly. Separately, the older X9.31 RSA signature scheme was removed, and the standard now permits larger RSA key sizes than before. RSA itself came through the revision essentially intact; it was the outdated padding conventions and the unrelated DSA algorithm that didn't.",[157,175,177],{"id":176},"fapis-restriction-isnt-on-rsa-its-on-one-specific-rsa-padding-scheme","FAPI's Restriction Isn't on RSA — It's on One Specific RSA Padding Scheme",[148,179,180,181,186,187,191,192,195,196,199,200,203],{},"This is where the confusion really originates, and it's worth being precise about it. The ",[164,182,185],{"href":183,"rel":184},"https://openid.net/specs/fapi-2_0-security-02.html",[168],"FAPI 2.0 Security Profile"," requires that authorization servers, clients, and resource servers use PS256, ES256, or EdDSA when creating or processing JWTs, and explicitly prohibits the ",[188,189,190],"code",{},"none"," algorithm. FAPI 1.0's Advanced profile said something even more pointed: implementations ",[152,193,194],{},"shall"," use PS256 or ES256, and ",[152,197,198],{},"should not"," use algorithms built on RSASSA-PKCS1-v1_5 — the family that includes the extremely common ",[188,201,202],{},"RS256",".",[148,205,206,207,211],{},"Here's the detail that gets lost: ",[208,209,210],"strong",{},"PS256 is RSA."," It stands for RSASSA-PSS using SHA-256 — a signature scheme built on the exact same RSA math as RS256. FAPI isn't asking implementers to abandon RSA. It's asking them to abandon one specific padding scheme (PKCS#1 v1.5) in favor of a newer one (PSS) built on the same underlying algorithm, alongside allowing elliptic-curve alternatives for anyone who wants to move off RSA entirely for other reasons like key size and performance.",[157,213,215],{"id":214},"why-pkcs1-v15-specifically-fell-out-of-favor","Why PKCS#1 v1.5 Specifically Fell Out of Favor",[148,217,218],{},"The distinction between RS256 and PS256 comes down to how the padding is constructed before the RSA operation runs, and it's not a cosmetic difference.",[148,220,221,222,227],{},"RSASSA-PKCS1-v1.5, the scheme behind RS256, is deterministic — the same message and key always produce the same signature — and it lacks a formal security proof under standard cryptographic assumptions. In practice, that gap between \"widely deployed\" and \"provably secure\" showed up as real vulnerabilities: a string of implementation bugs across multiple cryptography libraries over the years stemmed from verifiers that checked PKCS#1 v1.5 padding too permissively, allowing crafted signatures to be accepted as valid without the attacker ever having the private key. Best-practice guidance for JSON Web Tokens specifically — ",[164,223,226],{"href":224,"rel":225},"https://www.rfc-editor.org/rfc/rfc8725",[168],"RFC 8725, \"JSON Web Token Best Current Practices\""," — which FAPI 2.0 explicitly requires adherence to, reflects this history by steering implementers toward algorithms with better security properties and away from legacy defaults chosen more for compatibility than for security margin.",[148,229,230],{},"RSASSA-PSS, the scheme behind PS256, is randomized — it incorporates a salt, so the same message signed twice produces different signatures — and it comes with a security proof in the random oracle model. That's a meaningfully stronger guarantee, and it's the reason FAPI's high-assurance, financial-grade context specifically calls it out rather than treating RS256 and PS256 as interchangeable.",[157,232,234],{"id":233},"the-broader-pattern-algorithm-agility-not-algorithm-abandonment","The Broader Pattern: Algorithm Agility, Not Algorithm Abandonment",[148,236,237],{},"Both standards are really doing the same thing, just at different layers. FIPS 186-5 kept RSA but tightened the specific construction allowed and made room for elliptic-curve alternatives as a modern option. FAPI kept RSA-based signing available through PS256 but closed the door on the specific padding legacy that kept causing implementation bugs, while giving implementers ES256 and EdDSA as equally acceptable paths that don't involve RSA's larger keys and slower operations at all.",[148,239,240,241,244],{},"This is a pattern worth recognizing beyond these two standards specifically: modern cryptographic guidance rarely retires an algorithm family wholesale. It retires the ",[152,242,243],{},"specific, older construction"," of that algorithm once enough real-world weaknesses accumulate against it, while leaving a well-specified, better-analyzed version of the same underlying math in place. RSA the algorithm is fine. RSA-with-1990s-padding, applied without the scrutiny modern standards now require, is what's actually being phased out — and treating those as the same thing is exactly the kind of imprecision that leads engineering teams to either panic-migrate away from RSA entirely when they didn't need to, or worse, assume they're already compliant with PS256-based specs while still shipping RS256.",[157,246,248],{"id":247},"the-takeaway","The Takeaway",[148,250,251],{},"If your team is implementing FAPI or targeting FIPS compliance, the actionable question isn't \"should we stop using RSA.\" For most systems the answer is closer to: keep RSA if you want to, but make sure you're specifying RSASSA-PSS (PS256), not RSASSA-PKCS1-v1.5 (RS256), and check whether your libraries default to the older scheme without telling you — a surprising number still do, because RS256 has been the path-of-least-resistance default in JWT tooling for years. RSA was never asked to leave the room. It was asked to update how it signs things, and the standards are just being explicit about which version they'll actually accept.",[253,254],"hr",{},[157,256,258],{"id":257},"references-and-further-reading","References and Further Reading",[260,261,262,271,278,286,295],"ul",{},[263,264,265,266,270],"li",{},"NIST, ",[164,267,269],{"href":166,"rel":268},[168],"FIPS 186-5: Digital Signature Standard (DSS)"," (2023) — the current federal standard, confirming RSA, ECDSA, and EdDSA as the three approved signature algorithms.",[263,272,273,274,277],{},"OpenID Foundation, ",[164,275,185],{"href":183,"rel":276},[168]," — the specification requiring PS256, ES256, or EdDSA for JWT signing.",[263,279,280,281,285],{},"IETF, ",[164,282,284],{"href":224,"rel":283},[168],"RFC 8725: JSON Web Token Best Current Practices"," — the JWT security guidance FAPI 2.0 requires adherence to.",[263,287,288,289,294],{},"Authlete, ",[164,290,293],{"href":291,"rel":292},"https://www.authlete.com/kb/financial-grade-api/general-information/how-to-use-fapi/",[168],"\"How to Use FAPI\""," — a practical summary of FAPI 1.0 Advanced's explicit guidance against RSASSA-PKCS1-v1.5 algorithms like RS256.",[263,296,297,298,303],{},"Corsec, ",[164,299,302],{"href":300,"rel":301},"https://www.corsec.com/fips-186-5/",[168],"\"FIPS 186-5 Digital Signature Standard Compliance\""," — an overview of what changed between FIPS 186-4 and 186-5, including the removal of DSA and the X9.31 RSA scheme.",{"title":305,"searchDepth":306,"depth":307,"links":308},"",1,2,[309,310,311,312,313,314],{"id":159,"depth":307,"text":160},{"id":176,"depth":307,"text":177},{"id":214,"depth":307,"text":215},{"id":233,"depth":307,"text":234},{"id":247,"depth":307,"text":248},{"id":257,"depth":307,"text":258},"2026-07-25","RSA was never dropped from FIPS or FAPI. What changed is which padding scheme is allowed, and the gap between RS256 and PS256 is exactly where the myth comes from.","md",{},true,"/blog/rsa-fips-fapi-myth","6 min",{"title":143,"description":316},"blog/5.rsa-fips-fapi-myth","Security","xm9J_egzqNeOrwidC-VYN8eZVIWAbt2tJx0nBtq2imk",[327,332],{"title":328,"path":329,"stem":330,"description":331,"children":-1},"CIBA and the Case for Matching Auth Flows to Threat Models, Not Popularity","/blog/ciba-vs-authorization-code-banking","blog/4.ciba-vs-authorization-code-banking","Authorization Code Flow with PKCE is the default for native apps for good reason — but a bank's own first-party app has a different relationship with its identity provider, and CIBA was built for exactly that shape of problem.",{"title":333,"path":334,"stem":335,"description":336,"children":-1},"Password Security Was Never About Complexity — It's About Exposure","/blog/password-security-not-complexity","blog/6.password-security-not-complexity","Complexity rules check whether a password looks hard to guess. Attackers running credential stuffing don't care how a password is shaped — only whether it's already sitting in a breach dataset.",1785744836761]