PageSourceSearch

https://curity.io/component---src-templates-resource-article-js-co…kens-with-eddsa-mdx-66b35d592c48fde7b174.js

js curity.io collected 2026-09-24 09:29:10 UTC 17,704 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkcurity_website=self.webpackChunkcurity_website||[]).push([[11597],{35705:function(e,t,n){var r=n(74848),i=n(28453),o=n(5227);function s(e){return(0,r.jsx)(o.r,{target:"_blank",rel:"noopener noreferrer",href:"https://oauth.tools/?utm_source=curity.io&utm_medium=Link&utm_content={props.utmContent}",children:"OAuth Tools"})}t.A=function(e={}){const{wrapper:t}=Object.assign({},(0,i.RP)(),e.components);return t?(0,r.jsx)(t,Object.assign({},e,{children:(0,r.jsx)(s,e)})):s()}},37281:function(e,t,n){n.r(t),n.d(t,{Head:function(){return k},default:function(){return w}});var r=n(54506),i=n(74848),o=n(28453),s=n(5227),a=n(96370),c=n(27872),l=n(43745),d=n(35705);function h(e){const t=Object.assign({h2:"h2",p:"p",code:"code",ol:"ol",li:"li",em:"em",strong:"strong",img:"img",h3:"h3",pre:"pre"},(0,o.RP)(),e.components);return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{children:"Introduction to EdDSA"}),"\n",(0,i.jsxs)(t.p,{children:["EdDSA is a high performant, state-of-the-art digital signature scheme. There are two main variants: ",(0,i.jsx)(t.code,{children:"Ed25519"})," and ",(0,i.jsx)(t.code,{children:"Ed448"})," which are the names of the underlying Edwards Curves. One of the reasons for EdDSA's performance, is the small size of the public keys (32 or 57 bytes) and signatures (64 or 114 bytes). EdDSA is also very secure for several reasons:"]}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsxs)(t.li,{children:["EdDSA uses a deterministic nonce that removes the requirement of a random number generator compared to ECDSA. Poor generation of a nonce can ",(0,i.jsx)(s.r,{rel:"noopener noreferrer",href:"https://eprint.iacr.org/2013/734.pdf",children:"break an ECDSA system"}),". This vulnerability does not apply for EdDSA."]}),"\n",(0,i.jsx)(t.li,{children:"EdDSA is designed to be more resilient to side-channel attacks, that is, attacks that analyze for example power consumption or timing to gain information about the operation and keys. One method to mitigate the risk for side-channel attacks are constant-time implementations. There is no need for expensive point validation in EdDSA because of its complete formulas. Consequently, EdDSA is easier to implement and to implement securely."}),"\n",(0,i.jsxs)(t.li,{children:["The algorithm supported by the Curity Identity Server, also called ",(0,i.jsx)(t.em,{children:"PureEdDSA"})," is known to provide collision resilience. That means that collisions in the hash-function do not break the system."]}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["There has been enough time for researchers to ",(0,i.jsx)(s.r,{rel:"noopener noreferrer",href:"https://www.researchgate.net/publication/344671691_Taming_the_many_EdDSAs",children:"study EdDSA"})," since the publication of the ",(0,i.jsx)(s.r,{rel:"noopener noreferrer",href:"http://ed25519.cr.yp.to/ed25519-20110926.pdf",children:"original paper"})," in 2011.\nIn addition, with ",(0,i.jsx)(s.r,{rel:"noopener noreferrer",href:"https://www.rfc-editor.org/rfc/rfc8032",children:"RFC 8032"})," an implementation focused description was published. This enabled developers to add support for the algorithm in their products. With version 7.2, EdDSA is also available in the Curity Identity Server. This tutorial shows how to configure the Curity Identity Server to issue tokens with an EdDSA Signature."]}),"\n",(0,i.jsx)(t.h2,{children:"Import an EdDSA Key"}),"\n",(0,i.jsx)(t.p,{children:"If you do not have any key yet, use a tool of your choice to generate an EdDSA key pair. For example, test one of the following commands to generate a key:"}),"\n",(0,i.jsxs)(c.tU,{children:[(0,i.jsxs)(c.oz,{title:"Keytool",children:[(0,i.jsx)(t.p,{children:(0,i.jsx)(t.code,{children:"keytool -genkeypair -keyalg eddsa -keysize 255 -dname CN=tutorial,O=curityio -keystore eddsa-keystore.p12 -storepass Password1 -alias ed25519-key"})}),(0,i.jsxs)(t.p,{children:["This command uses Java's keytool to create a key-pair for EdDSA (",(0,i.jsx)(t.code,{children:"-keyalg"}),") with a length of 255 bits (",(0,i.jsx)(t.code,{children:"-keysize"}),"). This key can be used with the curve Ed25519. The command also creates a self-signed certificate with the given distinguished name (",(0,i.jsx)(t.code,{children:"-dname"}),"). The results are stored in the provided keystore (",(0,i.jsx)(t.code,{children:"-keystore"})," and ",(0,i.jsx)(t.code,{children:"-storepass"}),") under the given name (",(0,i.jsx)(t.code,{children:"-alias"}),"). The alias is used to identify the key in case there are several entries in the keystore."]})]}),(0,i.jsxs)(c.oz,{title:"OpenSSL",children:[(0,i.jsx)(t.p,{children:(0,i.jsx)(t.code,{children:"openssl genpkey -algorithm ed25519 -out ed25519-key.pem"})}),(0,i.jsx)(t.p,{children:"This is a simple and compact command that just creates the key pair and no certificate. The key can be used with the curve Ed25519."}),(0,i.jsx)(l.A,{kind:"warning",title:"Unprotected key",children:(0,i.jsx)(t.p,{children:"Use the command with caution! Do not use in production. The private key is unencrypted."})})]})]}),"\n",(0,i.jsxs)(t.p,{children:["With the key available, open the ",(0,i.jsx)(t.strong,{children:"Facilities"})," menu and navigate to ",(0,i.jsx)(t.strong,{children:"Keys and Cryptography"})," → ",(0,i.jsx)(t.strong,{children:"Signing"})," → ",(0,i.jsx)(t.strong,{children:"Signing Keys"}),". Click on ",(0,i.jsx)(t.strong,{children:"+"})," next to it. In the form enter a name and choose ",(0,i.jsx)(t.code,{children:"asymmetric"})," as the type of the new signing key."]}),"\n",(0,i.jsx)(t.img,{src:"/images/resources/howtos/configuration/eddsa/new-signing-key.jpg",alt:"Import existing Signing Key"}),"\n",(0,i.jsxs)(t.p,{children:["Click on ",(0,i.jsx)(t.strong,{children:"Upload Existing"}),". Select the keystore or file containing the private EdDSA key. Enter the password and alias if necessary."]}),"\n",(0,i.jsx)(t.img,{src:"/images/resources/howtos/configuration/eddsa/import-existing-signing-key.jpg",alt:"Import existing Signing Key"}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Add and Commit"})," the configuration."]}),"\n",(0,i.jsx)(t.h3,{children:"Verify the Key"}),"\n",(0,i.jsxs)(t.p,{children:["Open the ",(0,i.jsx)(t.strong,{children:"Facilities"})," menu and navigate to ",(0,i.jsx)(t.strong,{children:"Keys and Cryptography"})," → ",(0,i.jsx)(t.strong,{children:"Signing"})," → ",(0,i.jsx)(t.strong,{children:"Signing Keys"}),". Select the key with the name from above."]}),"\n",(0,i.jsx)(t.img,{src:"/images/resources/howtos/configuration/eddsa/eddsa-signing-key.jpg",alt:"
1Verify Signing Key"}),"\n",(0,i.jsxs)(t.p,{children:["Double-check the values: issuer, expiration dates and fingerprints of the certificate (if any); algorithm, curve and public key ",(0,i.jsx)(t.code,{children:"x"})," of the JWK."]}),"\n",(0,i.jsx)(t.p,{children:"EdDSA was designed with high performance in mind. You can literally see that. Take the time to acknowledge how small (short) the encoded public key is: 256 bits compared to several thousand bits for RSA keys; a single parameter compared to two for an elliptic curve key."}),"\n",(0,i.jsx)(t.h2,{children:"Issue Tokens with EdDSA"}),"\n",(0,i.jsxs)(t.p,{children:["To create tokens with an EdDSA signature, configure the Token Issuer with an EdDSA key. Select the Token Service from the profiles. Click on ",(0,i.jsx)(t.strong,{children:"Token Issuers"})," in the menu."]}),"\n",(0,i.jsx)(t.img,{src:"/images/resources/howtos/configuration/eddsa/configure-token-issuer.jpg",alt:"Configure Token Issuer"}),"\n",(0,i.jsxs)(t.p,{children:["Scroll down. Select ",(0,i.jsx)(t.code,{children:"EdDSA"})," from the drop-down for the algorithm. From the drop-down for the signing key select an appropriate EdDSA key, e.g. ",(0,i.jsx)(t.code,{children:"eddsa-signing-key"})," from the example above. ",(0,i.jsx)(t.strong,{children:"Commit"})," the changes."]}),"\n",(0,i.jsx)(t.img,{src:"/images/resources/howtos/configuration/eddsa/configure-eddsa-token-issuer.jpg",alt:"Configure Token Issuer"}),"\n",(0,i.jsxs)(t.p,{children:["The Curity Identity Server publishes its keys in a ",(0,i.jsx)(t.code,{children:"jwks_uri"}),". It was updated with the EdDSA key. When you navigate to the JWKS endpoint of your instance of the Curity Identity Server you can verify the key. If you use the default settings from the configuration wizard and run the server on localhost the JWKS endpoint will look like this: ",(0,i.jsx)(t.code,{children:"https://localhost:8443/oauth/v2/oauth-anonymous/jwks"}),". Enter the URL in a browser. The result looks similar to the following json and should match the key from above."]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-json",children:'{"keys": [\n  {\n    "kty":"OKP",\n    "kid":"1810805287",\n    "use":"sig",\n    "alg":"EdDSA",\n    "crv":"Ed25519",\n    "x":"9T2s4FQy0bg7AJ5w_k2gkgTLxHd0S1Fj6RRHEjn9tMw",\n    "x5t":"SUyrxNZQjpV0L93qk55tVldxlmk"\n  }\n]}\n'})}),"\n",(0,i.jsx)(t.h2,{children:"Testing"}),"\n",(0,i.jsxs)(t.p,{children:["The easiest way is to use ",(0,i.jsx)(d.A,{})," for retrieving and parsing tokens."]}),"\n",(0,i.jsxs)(t.p,{children:["However, you need a valid client configuration for testing. Download and import the ",(0,i.jsx)(s.r,{rel:"noopener noreferrer",href:"https://developer.curity.io/release/latest/configuration-samples",children:"sample configuration"})," from the developer portal or follow ",(0,i.jsx)(a.A,{file:"howtos/flows/code-flow.mdx",children:"other tutorials"})," to learn how to run certain flows to retrieve a token."]}),"\n",(0,i.jsx)(t.p,{children:"Here is an example for an access token with an EdDSA signature:"}),"\n",(0,i.jsxs)(c.tU,{children:[(0,i.jsxs)(c.oz,{title:"Decoded JWT",children:[(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Header"})}),(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-json",children:'{\n  "kid": "1810805287",\n  "x5t": "SUyrxNZQjpV0L93qk55tVldxlmk",\n  "x5t#S256": "T3aNpOk1rRfWuV9KFDigTGrKrY5Dv2qZXAKP6QAcvR0",\n  "alg": "EdDSA"\n}\n'})}),(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Payload"})}),(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-json",children:'{\n  "jti": "99c94a4a-00e5-4c05-9e3a-3167d7cc5939",\n  "delegationId": "c9c7270c-fe8a-4d94-8400-ae584346207d",\n  "exp": 1653906942,\n  "nbf": 1653906642,\n  "scope": "read openid",\n  "iss": "https://localhost:8443/oauth/v2/oauth-anonymous",\n  "sub": "testuser",\n  "aud": "testclient",\n  "iat": 1653906642,\n  "purpose": "access_token"\n}\n'})})]}),(0,i.jsx)(c.oz,{title:"Encoded JWT",children:(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"eyJraWQiOiIxODEwODA1Mjg3IiwieDV0IjoiU1V5cnhOWlFqcFYwTDkzcWs1NXRWbGR4bG1rIiwieDV0I1MyNTYiOiJUM2FOcE9rMXJSZld1VjlLRkRpZ1RHcktyWTVEdjJxWlhBS1A2UUFjdlIwIiwiYWxnIjoiRWREU0EifQ.eyJqdGkiOiI5OWM5NGE0YS0wMGU1LTRjMDUtOWUzYS0zMTY3ZDdjYzU5MzkiLCJkZWxlZ2F0aW9uSWQiOiJjOWM3MjcwYy1mZThhLTRkOTQtODQwMC1hZTU4NDM0NjIwN2QiLCJleHAiOjE2NTM5MDY5NDIsIm5iZiI6MTY1MzkwNjY0Miwic2NvcGUiOiJyZWFkIG9wZW5pZCIsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0Ojg0NDMvb2F1dGgvdjIvb2F1dGgtYW5vbnltb3VzIiwic3ViIjoidGVzdHVzZXIiLCJhdWQiOiJ0ZXN0Y2xpZW50IiwiaWF0IjoxNjUzOTA2NjQyLCJwdXJwb3NlIjoiYWNjZXNzX3Rva2VuIn0.u5k1G4jOA4bANyonCQ0q8K2jT6rX2V6vP4xEZalt2iWmajqHZp2peDZaQffwnNk6bS4oQSOtQ4a2A6AaUuJ5Bg\n"})})})]}),"\n",(0,i.jsxs)(t.p,{children:["Check out and take a deep dive into the code example for ",(0,i.jsx)(a.A,{file:"oauth-filter-for-java",children:"Securing a Java API with JWTs"}),". It supports the validation of EdDSA signed tokens and thus contains the code on how to validate an EdDSA signature in Java."]})]})}var u=function(e={}){const{wrapper:t}=Object.assign({},(0,o.RP)(),e.components);return t?(0,i.jsx)(t,Object.assign({},e,{children:(0,i.jsx)(h,e)})):h(e)},p=n(36117),m=n(94454),g=n(77528),f=n(63351),y=n(96540),j=n(32413);function x({data:{mdx:e},children:t}){const{frontmatter:n,internal:r}=e,{contentFilePath:i}=e.internal,o=(0,j.au)(i);return y.createElement(y.Fragment,null,y.createElement(m.A,{showArticleSidebarNav:!0,contentType:n.topic}),y.createElement(f.A),y.createElement(p.c,{articleSlug:o,frontmatter:n,children:t,path:r.contentFilePath}))}function w(e){return y.createElement(x,e,y.createElement(u,e))}const k=({data:{mdx:e},location:t})=>{const{frontmatter:n}=e,{contentFilePath:i}=e.internal,o=(0,j.au)(i),s=n.sharing_image?n.sharing_image:"/images/open-graph/homepage-sharing-image.jpg",a={"@context":"https://schema.org","@type":"TechArticle",mainEntityOfPage:{"@type":"WebPage","@id":`https://curity.io${o}`},headline:n.title,image:[`https://curity.io${s}`],datePublished:n.created||n.date,dateModified:n.date,...n.keywords?{keywords:n.keywords}:{},author:(0,j.fy)(n.author),url:`https://curity.io${o}`,description:n.description,publisher:{"@type":"Organization","@id":"https://curity.io/#organization"}},c=n.faq?{"@context":"https://schema.org","@type":"FAQPage",mainEntity:n.faq.map(e=>
1({"@type":"Question",name:e.question,acceptedAnswer:{"@type":"Answer",text:e.answer}}))}:null,l=Array.isArray(n.howto_steps)?n.howto_steps.filter(e=>e&&e.name&&e.text):[],d=(e=>{if(!e||"string"!=typeof e)return;const t=e.match(/(\d+)\s*(hour|hr|h|minute|min|m)/i);if(!t)return;const n=parseInt(t[1],10);if(Number.isNaN(n))return;return t[2].toLowerCase().startsWith("h")?`PT${n}H`:`PT${n}M`})(n.time),h=l.length>=2?{"@context":"https://schema.org","@type":"HowTo",name:n.title,description:n.description,...n.sharing_image?{image:`https://curity.io${n.sharing_image}`}:{},...d?{totalTime:d}:{},step:l.map((e,t)=>({"@type":"HowToStep",position:t+1,name:e.name,text:e.text,...e.url?{url:e.url.startsWith("#")?`https://curity.io${o}${e.url}`:e.url}:{}}))}:null,u={"@context":"https://schema.org","@type":"BreadcrumbList",itemListElement:[{"@type":"ListItem",position:1,name:"Home",item:"https://curity.io/"},{"@type":"ListItem",position:2,name:"Resources",item:"https://curity.io/resources/"},{"@type":"ListItem",position:3,name:n.title,item:`https://curity.io${o}`}]},p=[a].concat((0,r.A)(h?[h]:[]),[u],(0,r.A)(c?[c]:[]));return y.createElement(g.A,{title:null!==n.seo_title?n.seo_title:n.title,description:n.description,image:s,schemaMarkup:p,bodyClass:"resources  ",pathname:t.pathname})}},96370:function(e,t,n){var r=n(24794),i=(n(96540),n(32413)),o=n(74848);t.A=({file:e,anchor:t=null,children:n,tooltip:s=null,...a})=>{const c=e.split("/").pop(),l=null!=t?`#${t}`:"",d=-1===c.lastIndexOf(".")?c+".mdx":c,h=`${(0,i.au)(d)}${l}`;return(0,o.jsx)(r.Link,{to:h,className:"ref ref-cross","data-tooltip":s,...a,children:n})}},72563:function(e,t,n){n.d(t,{o:function(){return r}});const r=({title:e=null,children:t})=>t},41343:function(e,t,n){n.d(t,{K:function(){return s}});var r=n(96540),i=n(68589),o=n(74848);const s=(0,r.forwardRef)(function({activeTab:e,title:t,tabId:n,panelId:r,onSelect:s,onKeyDown:a},c){const l=e===t;return(0,o.jsx)("button",{ref:c,type:"button",role:"tab",id:n,className:l?i.vu:"","aria-selected":l,"aria-controls":r,tabIndex:l?0:-1,onClick:()=>s(t),onKeyDown:a,children:t})})},1942:function(e,t,n){n.d(t,{t:function(){return c}});var r=n(96540),i=n(96551),o=n(41343),s=n(68589),a=n(74848);const c=({name:e=null,type:t=null,color:n=null,placement:c=null,alignment:l=null,dark:d=!1,children:h})=>{var u;const p=r.Children.toArray(h).filter(Boolean),{0:m,1:g}=(0,r.useState)(null===(u=p[0])||void 0===u?void 0:u.props.title),f=(0,r.useRef)(null),y=(0,r.useRef)([]),j=(0,r.useRef)(!1),x=(0,r.useId)(),w=t=>{if(g(t),"undefined"==typeof window)return;const n=new URLSearchParams(window.location.search);e&&n.set("tabgroup",e),n.set("tab",t.replace(/ /g,"-")),window.history.replaceState(void 0,"",`?${n}`)},k=e=>{const t=(e+p.length)%p.length,n=p[t];n&&(w(n.props.title),requestAnimationFrame(()=>{var e;return null===(e=y.current[t])||void 0===e?void 0:e.focus()}))};(0,r.useEffect)(()=>{if(j.current||"undefined"==typeof window)return;j.current=!0;const t=new URLSearchParams(window.location.search),n=t.get("tab"),r=t.get("tabgroup");if(!n)return;const i=n.replace(/-/g," ");p.some(e=>e.props.title===i)&&g(i),r&&r===e&&f.current&&(f.current.scrollIntoView(),window.scrollBy(0,-200))},[]);const v=[s.pL];return"files"===t&&v.push(s.aq),(d||"dark"===n)&&v.push(s.XT),"primary"===n&&v.push(s.zB),"center"===c&&v.push(s.gX),"center"===l&&v.push(s.Hu),(0,a.jsxs)("div",{className:v.join(" "),ref:f,children:[(0,a.jsx)("div",{className:"m0 list-reset",role:"tablist",children:p.map((e,t)=>{const{title:n}=e.props;return(0,a.jsx)(o.K,{ref:e=>{y.current[t]=e},activeTab:m,title:n,tabId:`${x}-tab-${(0,i.Yv)(n)}`,panelId:`${x}-panel-${(0,i.Yv)(n)}`,onSelect:w,onKeyDown:e=>((e,t)=>{switch(e.key){case"ArrowRight":case"ArrowDown":e.preventDefault(),k(t+1);break;case"ArrowLeft":case"ArrowUp":e.preventDefault(),k(t-1);break;case"Home":e.preventDefault(),k(0);break;case"End":e.preventDefault(),k(p.length-1)}})(e,t)},n)})}),p.map(e=>{const{title:t}=e.props;return t!==m?null:(0,a.jsx)("div",{id:`${x}-panel-${(0,i.Yv)(t)}`,role:"tabpanel",tabIndex:0,"aria-labelledby":`${x}-tab-${(0,i.Yv)(t)}`,children:e.props.children},(0,i.Yv)(t))})]})}},27872:function(e,t,n){n.d(t,{oz:function(){return i.o},tU:function(){return r.t}});var r=n(1942),i=n(72563);n(41343)},68589:function(e,t,n){n.d(t,{Hu:function(){return i},Pb:function(){return a},XT:function(){return s},aq:function(){return c},gX:function(){return o},pL:function(){return d},vu:function(){return r},zB:function(){return l}});var r="Tabs-module--active--8c40b",i="Tabs-module--alignCenter--baa70",o="Tabs-module--center--f694d",s="Tabs-module--dark--02d12",a="Tabs-module--everythingThroughConfiguration--9a375",c="Tabs-module--files--d706f",l="Tabs-module--primary--b8dcc",d="Tabs-module--tabGroup--f5036"}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.