Created
January 14, 2016 03:49
-
-
Save fieldju/6c51e966388136df0bd4 to your computer and use it in GitHub Desktop.
POC for public private service to service auth mechinism
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import groovy.json.JsonBuilder | |
| import org.joda.time.DateTime | |
| import org.joda.time.DateTimeZone | |
| import org.joda.time.format.DateTimeFormatter | |
| import org.joda.time.format.ISODateTimeFormat | |
| import java.security.KeyPair | |
| import java.security.KeyPairGenerator | |
| import java.security.PrivateKey | |
| import java.security.PublicKey | |
| import java.security.Signature | |
| @GrabResolver(name="jcenter", root="http://jcenter.bintray.com/", m2Compatible=true) | |
| @GrabResolver(name="codehaus", root="http://repository.codehaus.org/", m2Compatible=true) | |
| /** | |
| * The dependencies | |
| */ | |
| @Grapes([ | |
| @Grab(group='joda-time', module='joda-time', version='2.9.1') | |
| ]) | |
| class Token { | |
| DateTime notBefore | |
| DateTime notAfter | |
| Token() { | |
| DateTime now = DateTime.now().withZone(DateTimeZone.UTC) | |
| notBefore = now.minusMinutes(5) | |
| notAfter = now.plusMinutes(5) | |
| } | |
| @Override | |
| String toString() { | |
| DateTimeFormatter formatter = ISODateTimeFormat.dateTime() | |
| new JsonBuilder([ | |
| notBefore: formatter.print(notBefore), | |
| notAfter: formatter.print(notAfter) | |
| ]).toString() | |
| } | |
| } | |
| class Service { | |
| private final MockDynamoDB mockDynamoDB | |
| Service() { | |
| mockDynamoDB = new MockDynamoDB() | |
| } | |
| Token generateToken() { | |
| return new Token() | |
| } | |
| String generateSignatureForToken(Token token, String keyId) { | |
| PrivateKey privateKey = mockDynamoDB.getPrivateKey(keyId) | |
| Signature rsa = Signature.getInstance("SHA1withRSA") | |
| rsa.initSign(privateKey) | |
| rsa.update(token.toString().bytes) | |
| String sig = rsa.sign().encodeBase64().toString() | |
| println "Generated sig: ${sig}" | |
| return sig | |
| } | |
| boolean verifySignatureForToken(Token token, String signature, String keyId) { | |
| try { | |
| PublicKey publicKey = mockDynamoDB.getPublicKey(keyId) | |
| Signature rsa = Signature.getInstance("SHA1withRSA") | |
| rsa.initVerify(publicKey) | |
| rsa.update(token.toString().bytes) | |
| boolean verified = rsa.verify(signature.decodeBase64()) | |
| assert verified, "Failed to verify token and signature" | |
| println "SUCCESS | token: $token was signed with keyid: ${keyId}" | |
| } catch (Exception e) { | |
| println "failed to verify token signature: ${e.getMessage()}" | |
| assert false | |
| } | |
| } | |
| } | |
| class MockDynamoDB { | |
| static final Map<String, KeyPair> data = [:] | |
| PrivateKey getPrivateKey(String keyId) { | |
| return getKeyPair(keyId).private | |
| } | |
| PublicKey getPublicKey(String keyId) { | |
| return getKeyPair(keyId).public | |
| } | |
| private KeyPair getKeyPair(String keyId) { | |
| KeyPair keyPair = data.get(keyId) | |
| if (keyPair == null) { | |
| KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA") | |
| kpg.initialize(2058) | |
| keyPair = kpg.genKeyPair() | |
| data.put(keyId, keyPair) | |
| } | |
| return keyPair | |
| } | |
| } | |
| def main() { | |
| Service a = new Service() | |
| Service b = new Service() | |
| String keyId = "ServiceAKey" | |
| Token serviceAToken = a.generateToken() | |
| String serviceASignature = a.generateSignatureForToken(serviceAToken, keyId) | |
| boolean verified = b.verifySignatureForToken(serviceAToken, serviceASignature, keyId) | |
| } | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment