-
Notifications
You must be signed in to change notification settings - Fork 829
JAV-501 Public key authentication between consumer and provider #330
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
21bb2df
bd0ef76
327da75
7c10133
ca32e83
be79407
5b3146c
f8abd61
3cf33db
14524df
06c997e
d06a771
ad13662
8e86e2c
eacffc4
5f288e6
8743f70
8923c22
d1fbfe5
8fb76d7
1647eb2
42be7b5
b042028
1953eb8
cf76cbe
6cf2ad8
aab1458
e35b62d
0398c71
2ee157c
7f3febb
417d2c9
d66a9a5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| /* | ||
| * Copyright 2017 Huawei Technologies Co., Ltd | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package io.servicecomb.foundation.common.utils; | ||
|
|
||
| import java.security.PrivateKey; | ||
| import java.security.PublicKey; | ||
|
|
||
| public final class RSAKeyPairEntry { | ||
|
|
||
| private PrivateKey privateKey; | ||
|
|
||
| private PublicKey publicKey; | ||
|
|
||
| private String publicKeyEncoded; | ||
|
|
||
| public RSAKeyPairEntry(PrivateKey privateKey, PublicKey publicKey, String publicKeyEncoded) { | ||
| this.privateKey = privateKey; | ||
| this.publicKey = publicKey; | ||
| this.publicKeyEncoded = publicKeyEncoded; | ||
| } | ||
|
|
||
| public PrivateKey getPrivateKey() { | ||
| return privateKey; | ||
| } | ||
|
|
||
| public PublicKey getPublicKey() { | ||
| return publicKey; | ||
| } | ||
|
|
||
| public String getPublicKeyEncoded() { | ||
| return publicKeyEncoded; | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| /* | ||
| * Copyright 2017 Huawei Technologies Co., Ltd | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package io.servicecomb.foundation.common.utils; | ||
|
|
||
| import java.security.InvalidKeyException; | ||
| import java.security.KeyFactory; | ||
| import java.security.KeyPair; | ||
| import java.security.KeyPairGenerator; | ||
| import java.security.NoSuchAlgorithmException; | ||
| import java.security.PrivateKey; | ||
| import java.security.PublicKey; | ||
| import java.security.SecureRandom; | ||
| import java.security.Signature; | ||
| import java.security.SignatureException; | ||
| import java.security.spec.InvalidKeySpecException; | ||
| import java.security.spec.X509EncodedKeySpec; | ||
| import java.util.Base64; | ||
|
|
||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| public class RSAUtils { | ||
|
|
||
| private final static Logger LOGGER = LoggerFactory.getLogger(RSAUtils.class); | ||
|
|
||
| private final static String RSA_ALG = "RSA"; | ||
|
|
||
| private final static String SIGN_ALG = "SHA256withRSA"; | ||
|
|
||
| private final static int KEY_SIZE = 2048; | ||
|
|
||
| private static Base64.Encoder encoder = Base64.getEncoder(); | ||
|
|
||
| private static Base64.Decoder decoder = Base64.getDecoder(); | ||
|
|
||
| private static KeyFactory kf = null; | ||
|
|
||
| static { | ||
|
|
||
| try { | ||
| kf = KeyFactory.getInstance(RSA_ALG); | ||
| } catch (NoSuchAlgorithmException e) { | ||
| LOGGER.error("init keyfactory error"); | ||
| } | ||
| } | ||
|
|
||
| public static RSAKeyPairEntry generateRSAKeyPair() { | ||
| try { | ||
| KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(RSA_ALG); | ||
| keyGenerator.initialize(KEY_SIZE, new SecureRandom()); | ||
| KeyPair keyPair = keyGenerator.generateKeyPair(); | ||
| PublicKey pubKey = keyPair.getPublic(); | ||
| PrivateKey privKey = keyPair.getPrivate(); | ||
| return new RSAKeyPairEntry(privKey, pubKey, encoder.encodeToString(pubKey.getEncoded())); | ||
| } catch (NoSuchAlgorithmException e) { | ||
| LOGGER.error("generate rsa keypair faild"); | ||
| throw new IllegalStateException("perhaps error occurred on jre"); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * if has performance problem ,change Signature to ThreadLocal instance | ||
| */ | ||
| public static String sign(String content, PrivateKey privateKey) | ||
| throws NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, InvalidKeyException { | ||
| Signature signature = Signature.getInstance(SIGN_ALG); | ||
| signature.initSign(privateKey); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Public and private key may not change in every call, for performance we can cache the init values. It is fine now and need more test data to evaluate
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is a good idea,but i think the RSAUtils is a common function; |
||
| signature.update(content.getBytes()); | ||
| byte[] signByte = signature.sign(); | ||
| return encoder.encodeToString(signByte); | ||
| } | ||
|
|
||
| /** | ||
| * | ||
| * if has performance problem ,change Signature to ThreadLocal instance | ||
| * @param publicKey public key after base64 encode | ||
| * @param sign 签名 | ||
| * @param content original content | ||
| * @return verify result | ||
| * @throws NoSuchAlgorithmException | ||
| * @throws InvalidKeySpecException | ||
| * @throws InvalidKeyException | ||
| * @throws SignatureException | ||
| */ | ||
| public static boolean verify(String publicKey, String sign, String content) | ||
| throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { | ||
| if (null == kf ) | ||
| { | ||
| throw new NoSuchAlgorithmException(RSA_ALG + " KeyFactory not available"); | ||
| } | ||
| byte[] bytes = decoder.decode(publicKey); | ||
| X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes); | ||
| PublicKey pubKey = kf.generatePublic(keySpec); | ||
| Signature signature = Signature.getInstance(SIGN_ALG); | ||
| signature.initVerify(pubKey); | ||
| signature.update(content.getBytes()); | ||
| return signature.verify(decoder.decode(sign)); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| package io.servicecomb.foundation.token; | ||
|
|
||
| import java.security.PrivateKey; | ||
| import java.security.PublicKey; | ||
|
|
||
| /** | ||
| * 进程级别公私钥对 | ||
| * | ||
| */ | ||
| public class RSAKeypair4Auth { | ||
|
|
||
| private RSAKeypair4Auth() { | ||
| }; | ||
|
|
||
| private PrivateKey privateKey; | ||
|
|
||
| private PublicKey publicKey; | ||
|
|
||
| private String publicKeyEncoded; | ||
|
|
||
|
|
||
| public PrivateKey getPrivateKey() { | ||
| return privateKey; | ||
| } | ||
|
|
||
|
|
||
| public void setPrivateKey(PrivateKey privateKey) { | ||
| this.privateKey = privateKey; | ||
| } | ||
|
|
||
|
|
||
| public PublicKey getPublicKey() { | ||
| return publicKey; | ||
| } | ||
|
|
||
|
|
||
| public void setPublicKey(PublicKey publicKey) { | ||
| this.publicKey = publicKey; | ||
| } | ||
|
|
||
|
|
||
| public String getPublicKeyEncoded() { | ||
| return publicKeyEncoded; | ||
| } | ||
|
|
||
|
|
||
| public void setPublicKeyEncoded(String publicKeyEncoded) { | ||
| this.publicKeyEncoded = publicKeyEncoded; | ||
| } | ||
|
|
||
| public static RSAKeypair4Auth INSTANCE = new RSAKeypair4Auth(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| /* | ||
| * Copyright 2017 Huawei Technologies Co., Ltd | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package io.servicecomb.foundation.common.utils; | ||
|
|
||
| import java.security.InvalidKeyException; | ||
| import java.security.NoSuchAlgorithmException; | ||
| import java.security.SignatureException; | ||
| import java.security.spec.InvalidKeySpecException; | ||
|
|
||
| import org.junit.Assert; | ||
| import org.junit.Test; | ||
|
|
||
| public class TestRSAUtil { | ||
|
|
||
| @Test | ||
| public void testSignVerify() | ||
| throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, SignatureException { | ||
| RSAKeyPairEntry rsaKeyPairEntry = RSAUtils.generateRSAKeyPair(); | ||
|
|
||
| Assert.assertNotNull(rsaKeyPairEntry.getPublicKeyEncoded()); | ||
| Assert.assertNotNull(rsaKeyPairEntry.getPrivateKey()); | ||
| Assert.assertNotNull(rsaKeyPairEntry.getPublicKey()); | ||
| String testContent = "instance-id@201711201930@randomstr"; | ||
| String signstr = RSAUtils.sign(testContent, rsaKeyPairEntry.getPrivateKey()); | ||
| Assert.assertTrue(RSAUtils.verify(rsaKeyPairEntry.getPublicKeyEncoded(), signstr, testContent)); | ||
|
|
||
| } | ||
|
|
||
| @Test | ||
| public void testSignVerify2() | ||
| throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, SignatureException { | ||
| String sign = | ||
| "WBYouF6hXYrXzBA31HC3VX8Bw9PNgJUtVqOPAaeW9ye3q/D7WWb0M+XMouBIWxWY6v9Un1dGu5Rkjlx6gZbnlHkb2VO8qFR3Y6lppooWCirzpvEBRjlJQu8LPBur0BCfYGq8XYrEZA2NU6sg2zXieqCSiX6BnMnBHNn4cR9iZpk="; | ||
| String content = | ||
| "e8a04b54cf2711e7b701286ed488fc20@c8636e5acf1f11e7b701286ed488fc20@1511315597475@9t0tp8ce80SUM5ts6iRGjFJMvCdQ7uvhpyh0RM7smKm3p4wYOrojr4oT1Pnwx7xwgcgEFbQdwPJxIMfivpQ1rHGqiLp67cjACvJ3Ke39pmeAVhybsLADfid6oSjscFaJ"; | ||
| String pubKey = | ||
| "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxKl5TNUTec7fL2degQcCk6vKf3c0wsfNK5V6elKzjWxm0MwbRj/UeR20VSnicBmVIOWrBS9LiERPPvjmmWUOSS2vxwr5XfhBhZ07gCAUNxBOTzgMo5nE45DhhZu5Jzt5qSV6o10Kq7+fCCBlDZ1UoWxZceHkUt5AxcrhEDulFjQIDAQAB"; | ||
| Assert.assertTrue(RSAUtils.verify(pubKey, sign, content)); | ||
|
|
||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| <!-- | ||
| ~ Copyright 2017 Huawei Technologies Co., Ltd | ||
| ~ | ||
| ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
| ~ you may not use this file except in compliance with the License. | ||
| ~ You may obtain a copy of the License at | ||
| ~ | ||
| ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
| ~ | ||
| ~ Unless required by applicable law or agreed to in writing, software | ||
| ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
| ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| ~ See the License for the specific language governing permissions and | ||
| ~ limitations under the License. | ||
| --> | ||
|
|
||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
| <parent> | ||
| <groupId>io.servicecomb</groupId> | ||
| <artifactId>handlers</artifactId> | ||
| <version>0.4.1-SNAPSHOT</version> | ||
| </parent> | ||
|
|
||
| <artifactId>handler-publickey-auth</artifactId> | ||
|
|
||
| <properties> | ||
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| </properties> | ||
|
|
||
| <dependencies> | ||
| <dependency> | ||
| <groupId>io.servicecomb</groupId> | ||
| <artifactId>java-chassis-core</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.slf4j</groupId> | ||
| <artifactId>slf4j-log4j12</artifactId> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>log4j</groupId> | ||
| <artifactId>log4j</artifactId> | ||
| <scope>test</scope> | ||
| </dependency> | ||
|
|
||
| </dependencies> | ||
|
|
||
| </project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| /* | ||
| * Copyright 2017 Huawei Technologies Co., Ltd | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package io.servicecomb; | ||
|
|
||
| import io.servicecomb.core.BootListener; | ||
| import io.servicecomb.foundation.common.utils.RSAKeyPairEntry; | ||
| import io.servicecomb.foundation.common.utils.RSAUtils; | ||
| import io.servicecomb.foundation.token.RSAKeypair4Auth; | ||
| import io.servicecomb.serviceregistry.RegistryUtils; | ||
| import io.servicecomb.serviceregistry.api.Const; | ||
|
|
||
| import org.springframework.stereotype.Component; | ||
|
|
||
| /** | ||
| * | ||
| * initialize public and private key pair when system boot before registry instance to service center | ||
| * | ||
| * | ||
| */ | ||
| @Component | ||
| public class AuthHandlerBoot implements BootListener { | ||
|
|
||
|
|
||
| @Override | ||
| public void onBootEvent(BootEvent event) { | ||
| if (EventType.BEFORE_REGISTRY.equals(event.getEventType())) { | ||
| RSAKeyPairEntry rsaKeyPairEntry = RSAUtils.generateRSAKeyPair(); | ||
| RSAKeypair4Auth.INSTANCE.setPrivateKey(rsaKeyPairEntry.getPrivateKey()); | ||
| RSAKeypair4Auth.INSTANCE.setPublicKey(rsaKeyPairEntry.getPublicKey()); | ||
| RSAKeypair4Auth.INSTANCE.setPublicKeyEncoded(rsaKeyPairEntry.getPublicKeyEncoded()); | ||
| RegistryUtils.getMicroserviceInstance().getProperties().put(Const.INSTANCE_PUBKEY_PRO, rsaKeyPairEntry.getPublicKeyEncoded()); | ||
| } | ||
|
|
||
| } | ||
|
|
||
|
|
||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
copy right
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
accept