1. 如何创建JWK

下面展示一个JWK案例

一个典型公钥JWK的案例:公钥和对应的私钥

公钥

{
    "kty": "RSA",
    "kid": "6ad0d632198de9ad926bf617e79cf412",
    "alg": "ES256",
    "n": "jy1H4f2XXsBAynu145alDhPIQ1lldTAYMLBJG2YguRd5aZ3oecZHh9Bu4qg1hw1GmNcaPG3iKUwSD-BiPw2CQfukOcdDq2oBnYYwf3EzmbwpJ5y4sk1k5aMRWh3n3atdcuNWiP_EErGLTde0_a_gkRXg39XNnHEaH5k4mY0HtBPQ7nvd1GZYsq9hbbxej3IyIUWRzjP_txuxWV7j41UkzFfjvq6xRAy-WgkZ3rHsXWU5jNRJugpYF-_P4L8C8vmHAYQUy41-YeK4-E30XIzbOL2LENAq1DnuzfdPbNX31BYn1chwQCw56mGoDqUrac-booeTjg-CYQv4r6c53urqcw",
    "e": "AQAB"
}

私钥

{
    "kty": "RSA",
    "kid": "6ad0d632198de9ad926bf617e79cf412",
    "alg": "ES256",
    "n": "jy1H4f2XXsBAynu145alDhPIQ1lldTAYMLBJG2YguRd5aZ3oecZHh9Bu4qg1hw1GmNcaPG3iKUwSD-BiPw2CQfukOcdDq2oBnYYwf3EzmbwpJ5y4sk1k5aMRWh3n3atdcuNWiP_EErGLTde0_a_gkRXg39XNnHEaH5k4mY0HtBPQ7nvd1GZYsq9hbbxej3IyIUWRzjP_txuxWV7j41UkzFfjvq6xRAy-WgkZ3rHsXWU5jNRJugpYF-_P4L8C8vmHAYQUy41-YeK4-E30XIzbOL2LENAq1DnuzfdPbNX31BYn1chwQCw56mGoDqUrac-booeTjg-CYQv4r6c53urqcw",
    "e": "AQAB",
    "d": "AZwvv8HbTux4jg5gGEQcbREZ4nAB7RRyYTHKUK2QVqSF8AMflyb8rPFSHehoWbFzhsp8eAuATJiXZ2hNkonzWgybZy7veuEBTaUxrG04eFUeXVys0wx9wvtXeZz2e46uyVj3IylFKjSm7WQsm-G7c8Y8NigwXL8E3TAa69cjLAo8ss1bR6-JMId5zAvlAZHKceAnEzAFQjj_BODDAEYhc8Mvzxf5GTW01ABs5o4LTK0KWHmuKT5Ai7U61DIDp8BEqqaDuz7w3HVINBySuQGO3BR0VtwPsUL4m0_LxMb3Gu5RRZpYRnT323vTUFm66AXQqZsDRO4hgSahiQDTQxk_QQ",
    "p": "yEZC0BBgVm5m0Lu84uZ4oxhKXXFoo1iC5j1Ilc4rwUGILFCFSULK3_zIB9xTQvLMqPkm4GEF2eQMoCjyrJg495BTZ9Ipk0qxJCklCUTQ_e5vFdAtp_K-ci2S85AsKR1-q5vuA2E-g9-HCGUUJ4834BmZE-nFeC5i_MdrrSsI7JM",
    "q": "twPnvo3mcWW-5k903teXQKYgCo_SgBABnEK4Nswr6lpOplAEhR6Auf5Wo-ekh9H9SjtwwDZ8Z0qLHozH36QSCyDjbi-w_mdh-yRW055o5LXgjGqGh_qb1iVJ7pf6yCZK_zTGqx23ET1UnYRiYWDEpowrrSo6mvJaPmD8lhuQlqE",
    "dp": "e2y5nkqJZJrTaE5bASbyL-k3Y1ESIKDawxP_mLsfwhEl39Gb4uNz7gh2KkoBUiAaOwSZjeydU4Q0t7ukmvORIBjlHfWqQ6jjdJqaxZSQi_4WncXXbUqvTeSCTPKMFKaluxL040ZZ5aGrMWRBwIOF9ukvqtMGLKPBw3EPDgCYlls",
    "dq": "M24shNc5qCpQkEZJ8ImjXq6QmIc8P3LAERqKzBNqT-xa58_axVICGMKJtHvXN7fiNycnE0z8fsZq_AXR8V4ZF_mBECjk00lYNoxKviNpFMSruqoA7luVyYMnGJ6rAe4I61j4b4PlOzoB-lYGk5jvCmKfr4ULfRmYFKmKseBDLKE",
    "qi": "kjvP5kanvQOccxpl4cK13YlRAvsrYmVVFt9coc-6odPgM2jN_lRjcCws96856PEkUVLwoo6sB6Y_qfO1orSfApRQ7nQJmYvOohu-zjyDq2GiQ6lUDn5LoDfafQyYqSEEM0U8j6_f0pWRlm-0Suzg5wrsodPzBeHktbxwi4JIYQE"
}

我们使用阿里云推荐的java代码来生成JWK密钥对,运行本工具需要java8的环境

下面讲解怎么创建一个JWK

  1. 下载生成JWK的java代码压缩包(http://doc.xdua.com/ref/jwk/jwk_generator.tar)

    生成的目录结构如下,其中所有的jar文件都是用来辅助生成key和生成token,运行genkey.sh可以根据一个32位种子生成一个秘钥对

    jwk_generator/
    ├── com.springsource.org.apache.log4j-1.2.16.jar
    ├── Genkey.class
    ├── Genkey.java
    ├── genkey.sh
    ├── Gentoken.class
    ├── Gentoken.java
    ├── gentoken.sh
    ├── jose4j-0.6.3.jar
    ├── README.md
    ├── slf4j-api-1.7.25.jar
    └── slf4j-log4j12-1.7.25.jar
    
  2. 自己制作一个32位的字符串作为kid,这个kid很重要,不能让任何第三方知道,这里我们使用一个示例kid:6ad0d632198de9ad926bf617e79cf412

    把这个kid放到genkey.sh脚本中,然后运行,会启动编译和执行,生成一个公私密钥对

    javac -cp .:./jose4j-0.6.3.jar Genkey.java
    java -cp .:./jose4j-0.6.3.jar Genkey 6ad0d632198de9ad926bf617e79cf412
    #注意-cp后面要有两个符号.: ,否则就报Could not find or load main class错误了
    

    输出结果入下图

    publicKey-----------------------start
    {"kty":"RSA","kid":"6ad0d632198de9ad926bf617e79cf412","alg":"ES256","n":"qZG5bGi4UV_IQV1jh4btrM1NPjtQGFUNI9OvupQXFuWLkfU8QU2CflqZ9d1yvh8kpRj2JimPr5y0kv2h3XaO2VCYZInVkoHRrb0XkSZA3LcExb83nLMUCDUQxrMfE4rW5dgTaw3UMJRVGT7Bebw8NlAIdwpeTKMzJQWcLHjU7Ogle899hJHRap8LXDfX3_WWE7wIvQkbjRqwuYSzZZOzJEslZRdKkDBdESRM36yNOuG8uiPOFJOcmtd4bWmrN66LTMX1pu89e2bCuITrkgRBjzihhOXc-TqeAi-ADpWiwI3kzocubHBnXgTN7sMQsLDf3IB5_YkdbxQ_gBLv3pqREw","e":"AQAB"}
    publicKey-----------------------finish
    
    privateKey-----------------------start
    {"kty":"RSA","kid":"6ad0d632198de9ad926bf617e79cf412","alg":"ES256","n":"qZG5bGi4UV_IQV1jh4btrM1NPjtQGFUNI9OvupQXFuWLkfU8QU2CflqZ9d1yvh8kpRj2JimPr5y0kv2h3XaO2VCYZInVkoHRrb0XkSZA3LcExb83nLMUCDUQxrMfE4rW5dgTaw3UMJRVGT7Bebw8NlAIdwpeTKMzJQWcLHjU7Ogle899hJHRap8LXDfX3_WWE7wIvQkbjRqwuYSzZZOzJEslZRdKkDBdESRM36yNOuG8uiPOFJOcmtd4bWmrN66LTMX1pu89e2bCuITrkgRBjzihhOXc-TqeAi-ADpWiwI3kzocubHBnXgTN7sMQsLDf3IB5_YkdbxQ_gBLv3pqREw","e":"AQAB","d":"H3m6RoJFvG0gGeoA4JZOJeZR8TxHSMz4zG6tzt9QTeK7_pLb5W9Cyrt8mqPJebsELVUt07WhQ0K-Tg6gbiBksbgBIaBoMXLBfhN8fWfxYEbkruQoqYCgNknLXGbBXPpHm5B5QkTl30KZbT814KftMVO3zojxKh6dDsE01Rh0xaigBN57xzjPA3p3XmAh3TAobYcV_BCpxD1FKVxMavoG7Kc0ZoCYHk6eU4NrHrqEsLzqMxE3U7iEezGZhgLv-vJ5tlXjv9nxQGTafro3kTaj4II62vsapGI_iBJR1zlcT-QpXkY6afKj-dEWm9ZbKfiBcY1wITLFh0WxAxCfEawUiQ","p":"6GfgynZ_Xl2_AleC1Ax9sPAPkml3pnZb1Lnw36Zgn9olTw1glIzXja1xj8jCueylSjXyqGmd7jUOuQxArzyBinDQIYIv0IxzPHxENzrSkdiZ1Mv2Yv4XSDMXGFaN9aJGiNWMo0S_fJEhuuZ7wqOxB_-s9M0Y2W7A9f4WKKQYQF8","q":"usjAtGhxkDCukGXLIItZpFScdUABNFatJyd3lz1ZSxV-OIo9jDjIeiiXThRVJBEnXNIGYKJl548iRkz4Hs-13AlGvbHwNAthJRAmj8c08kBUcZOVT5v1Wxr2Rg7fzsMl-mHplrRZD2hA28BZ2Df6Z7fP-HRppHyradC93_27G80","dp":"o532YTOZqhr_zatEfPsqRjZMEDzWMshjEFmz3hCpOAEBgS0e0JZzbtgr-hlSFkkneR6P7sckm76Y1ehtZbGIVankraKU_RLUUkH-WI--DVXbvze1B65xP7BQUx8kpEkRtWX6tDtDQHSAta9sc_SAPuxenJ4EH5fcm5K9kPEt7as","dq":"JVpUPz_LxhwWLMZOktmLObO5_jCojQDwa64W2mXoX32S2le66znHzbYkW_bw999-Ua-mmtifLGmRXyGxVOgQ5Enunazh7maALNtH-uTJj9CRko0DBQKZVHjV2zjKRRz9kU7XWc4DKXOd1NRooza-mtNFgdg18DEGTojyD8M8Edk","qi":"FaWlmA8Gpk4NEXDSA4dy3mfCYNK6e8TbCVB5O_JXzK-z0eaQA7O8PHQ08A40HTZclqYtICT5ihrE2MIihySKi10IgNyu5iAPssCwtaV_J50IyBKl15AXPRPVhy6Em3AuQ1CJPxlvBm0OPvMPR3HXF4ZN4A6ft5RpRqmZVLfMmMI"}
    privateKey-----------------------finish
    

    其实是调用Genkey.java的代码,代码参考于阿里云的API网关的示例代码

    import java.security.PrivateKey;
    import org.jose4j.json.JsonUtil;
    import org.jose4j.jwk.RsaJsonWebKey;
    import org.jose4j.jwk.RsaJwkGenerator;
    import org.jose4j.jws.AlgorithmIdentifiers;
    import org.jose4j.jws.JsonWebSignature;
    import org.jose4j.jwt.JwtClaims;
    import org.jose4j.jwt.NumericDate;
    import org.jose4j.lang.JoseException;
    public class Genkey {
        public static void main(String[] args) throws Exception {
            try{
                String keyId = args[0];
                //String keyId = "b50b1effdc035e2869b6c45f33bdf5d7";
                RsaJsonWebKey jwk = RsaJwkGenerator.generateJwk(2048);
                jwk.setKeyId(keyId);
                jwk.setAlgorithm(AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256);
                String publicKey = jwk.toJson(RsaJsonWebKey.OutputControlLevel.PUBLIC_ONLY);
                String privateKey = jwk.toJson(RsaJsonWebKey.OutputControlLevel.INCLUDE_PRIVATE); 
    
                System.out.println("\npublicKey-----------------------start\n");
                System.out.println(publicKey);
                System.out.println("\npublicKey-----------------------finish\n");
                System.out.println("\nprivateKey-----------------------start\n");
                System.out.println(privateKey);
                System.out.println("\nprivateKey-----------------------finish\n");
            } catch(Exception e) {
                //将sqrt方法声明的可能抛出的Exception异常捕获
                System.out.println("Got a Exception:" + e.getMessage());
                e.printStackTrace();
            }
        }
    }
    
  3. 用生成的秘钥生成一个token 文件夹下的gentoken.sh可以用刚刚的秘钥生成一个token

    javac -cp .:./com.springsource.org.apache.log4j-1.2.16.jar:./slf4j-api-1.7.25.jar:./slf4j-log4j12-1.7.25.jar:./jose4j-0.6.3.jar Gentoken.java
    java  -cp .:./com.springsource.org.apache.log4j-1.2.16.jar:./slf4j-api-1.7.25.jar:./slf4j-log4j12-1.7.25.jar:./jose4j-0.6.3.jar Gentoken
    

    下面展示了Gentoken.java的全部

    import java.security.PrivateKey;
    import org.jose4j.json.JsonUtil;
    import org.jose4j.jwk.RsaJsonWebKey;
    import org.jose4j.jwk.RsaJwkGenerator;
    import org.jose4j.jws.AlgorithmIdentifiers;
    import org.jose4j.jws.JsonWebSignature;
    import org.jose4j.jwt.JwtClaims;
    import org.jose4j.jwt.NumericDate;
    import org.jose4j.lang.JoseException;
    
    public class Gentoken {
        public static void main(String[] args) throws Exception {
            try{
                String privateKeyText = "{\"kty\":\"RSA\",\"kid\":\"6ad0d632198de9ad926bf617e79cf412\",\"alg\":\"ES256\",\"n\":\"sBZDgQUcSYv-OVwjwluFBCpDm8eqmrlmWGk1fp8qdSPGt7JLII2aLqXarxeguA2l7tqHfz8c8ItpHDyUKlL2LfUQLIWFA37QG1JBpXqE24UlE01fHfdrvzwHm_bHW-5RLaNltb0W3WWfOrBIrrurRWaCBF59z2XkmA-_nw_YJybpWBsB0lhCvU_jnx8MQnlHvh19HUVSTGo9BxwhrS8No7UQe7FPxvZr9ui6XEm9lPWdgXrklNPwXtDFapV_4Qj4XnUrSgnZrcBju-B75bjfwS5KgUlTN75-kHcozrqntquyWBfEQc2Ct2_j61a1qCuTtEiK9W-C4GYSRq8Mjb7BRw\",\"e\":\"AQAB\",\"d\":\"cFr0Xam-H-uUnlL9ejFdUYgKNacUY79y32zaNl4nADGAxYudRjs0KxmmzNwdr_L9cse7d2T0-UNrIRpCTDM9Y5uf41iaw90xuo0k2AqyJUPyoTtYOs250X7jOBAhqrYI1D8TUgBCS6hhDliXN-8FXLYItfL5AdH5J1G9Kig4-tlYefkM2scZ7IiS8g7o-EZauZFhHSdCKWD7KO3XkdvqV3R2zGb06ANFlqkOzopo8eOkYfqAqTExe8dTMNUwfJHtzNR4tf2UcWqGt9sEbrdw9K8GjJZNCcXYiJFgDgKUkn-aOARwuDvjmNKmtS4HBYaT50yKwUBod7eMLiGHtse-EQ\",\"p\":\"5ZVC3bVmUvTTM9EJx6mV4Xhu8U4xsbOQDEfVb9OdDl6xd-_dnKJkHCqif2igfdr598P-cHC2DzW_O5Bwt2xSp-Ywgji_3bftfVh-BL_CTriMo8KhOIDtyZuWhv3ZL62D5Tbrqs48whd6sW-WFyA6OEqDoTBdzNdtCAP88fytBbk\",\"q\":\"xFkwafo1qLjkOUTIHpQ6PrTttsZ8P7bDWjYgfz98JARkb9YX5vDHcKq6efYCt7uFqg1la0v6NYn2EEOMZosj6zVvAizdzrBQ2fI3cepqhH7KZCi5z6vYcv8dJkX9MQPVn1os696iSvHw4MTnnug-MMl7iRy4wuvAualRsNO9fv8\",\"dp\":\"RnNyTHTRDJ3ifeEk3idVPhZl_RiguUY_6vTUM3e9l15JmWN7HwjaLaaLrQtfTJ-422ZCmyCLTcmRgGbHoBHWn31M33kor5I0h6VzLmPl7aBGUC52qM8vqRFctNoLHs1hTyJ2WTjmfi0UUoTKixgxpXqAQCOGdUiaRb5rjZqbQck\",\"dq\":\"uUpJi9kZRi2lAf5Ms77B8GchZTiODDpWxA0MQckRR5P1jCyHxeI287XJ4EouamDGVKHrsYOzjU6yLMrx9dscfFyic3UPpHty8RnJBPFor7xPFpHwN3A-BNeHFJU7yEOMFqMsfTJOCVekLxjiU21rMvMQZ2X5XcjIyOxmMO7AhtU\",\"qi\":\"odqlkxgyQJu8ypVHJRhQN12O5DdAOlIG2OwMRS4tGB35tw77wjMpQTtS5dtDTNdc714EEpZz4bD0G1kmj3u5Fw_AfCrxDVMnxKsfjp-lAFJ-25aWP_Qm8f27OOmmBjBqtrr-YfZNn56wERBu5S3EiD0IJTBKsmZ6HKpe_93VJ7s\"}";
                String keyId = "6ad0d632198de9ad926bf617e79cf412";
                JwtClaims claims = new JwtClaims();
                claims.setGeneratedJwtId();
                claims.setIssuedAtToNow();
                //expire time
                NumericDate date = NumericDate.now();
                date.addSeconds(120);
                claims.setExpirationTime(date);
                claims.setNotBeforeMinutesInThePast(1);
                claims.setSubject("YOUR_SUBJECT");
                claims.setAudience("YOUR_AUDIENCE");
                //添加自定义参数
                //claims.setClaim(key, value);
                JsonWebSignature jws = new JsonWebSignature();
                jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
                jws.setKeyIdHeaderValue(keyId);
                jws.setPayload(claims.toJson());
                PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyText)).getPrivateKey();
                jws.setKey(privateKey);
                String idToken = jws.getCompactSerialization();
                System.out.println("\n----------------\n");
                System.out.println(idToken);
            } catch(Exception e) {
                //将sqrt方法声明的可能抛出的Exception异常捕获
                System.out.println("Got a Exception:" + e.getMessage());
                e.printStackTrace();
            }
        }
    }
    

results matching ""

    No results matching ""