Java tutorial
/* * Copyright 2012 the original author or authors. * * 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 org.brekka.phalanx.webservices; import java.util.UUID; import org.apache.xmlbeans.XmlObject; import org.brekka.phalanx.api.beans.IdentityCryptedData; import org.brekka.phalanx.api.beans.IdentityKeyPair; import org.brekka.phalanx.api.beans.IdentityPrincipal; import org.brekka.phalanx.api.model.AuthenticatedPrincipal; import org.brekka.phalanx.api.model.CryptedData; import org.brekka.phalanx.api.model.ExportedPublicKey; import org.brekka.phalanx.api.model.KeyPair; import org.brekka.phalanx.api.model.Principal; import org.brekka.phalanx.api.model.PrivateKeyToken; import org.brekka.phalanx.api.services.PhalanxService; import org.brekka.phalanx.core.services.PhalanxSessionService; import org.brekka.xml.phalanx.v2.model.AuthenticatedPrincipalType; import org.brekka.xml.phalanx.v2.model.CryptedDataIdType; import org.brekka.xml.phalanx.v2.model.KeyPairIdType; import org.brekka.xml.phalanx.v2.model.PrincipalIdType; import org.brekka.xml.phalanx.v2.model.PrincipalType; import org.brekka.xml.phalanx.v2.model.UUIDType; import org.brekka.xml.phalanx.v2.wsops.AssignKeyPairRequestDocument; import org.brekka.xml.phalanx.v2.wsops.AssignKeyPairRequestDocument.AssignKeyPairRequest; import org.brekka.xml.phalanx.v2.wsops.AssignKeyPairResponseDocument; import org.brekka.xml.phalanx.v2.wsops.AssignKeyPairResponseDocument.AssignKeyPairResponse; import org.brekka.xml.phalanx.v2.wsops.AsymmetricDecryptionRequestDocument; import org.brekka.xml.phalanx.v2.wsops.AsymmetricDecryptionRequestDocument.AsymmetricDecryptionRequest; import org.brekka.xml.phalanx.v2.wsops.AsymmetricDecryptionResponseDocument; import org.brekka.xml.phalanx.v2.wsops.AsymmetricDecryptionResponseDocument.AsymmetricDecryptionResponse; import org.brekka.xml.phalanx.v2.wsops.AsymmetricEncryptionRequestDocument; import org.brekka.xml.phalanx.v2.wsops.AsymmetricEncryptionRequestDocument.AsymmetricEncryptionRequest; import org.brekka.xml.phalanx.v2.wsops.AsymmetricEncryptionResponseDocument; import org.brekka.xml.phalanx.v2.wsops.AsymmetricEncryptionResponseDocument.AsymmetricEncryptionResponse; import org.brekka.xml.phalanx.v2.wsops.AuthenticateRequestDocument; import org.brekka.xml.phalanx.v2.wsops.AuthenticateRequestDocument.AuthenticateRequest; import org.brekka.xml.phalanx.v2.wsops.AuthenticateResponseDocument; import org.brekka.xml.phalanx.v2.wsops.AuthenticateResponseDocument.AuthenticateResponse; import org.brekka.xml.phalanx.v2.wsops.ChangePasswordRequestDocument; import org.brekka.xml.phalanx.v2.wsops.ChangePasswordRequestDocument.ChangePasswordRequest; import org.brekka.xml.phalanx.v2.wsops.ChangePasswordResponseDocument; import org.brekka.xml.phalanx.v2.wsops.CloneKeyPairPublicRequestDocument; import org.brekka.xml.phalanx.v2.wsops.CloneKeyPairPublicRequestDocument.CloneKeyPairPublicRequest; import org.brekka.xml.phalanx.v2.wsops.CloneKeyPairPublicResponseDocument; import org.brekka.xml.phalanx.v2.wsops.CloneKeyPairPublicResponseDocument.CloneKeyPairPublicResponse; import org.brekka.xml.phalanx.v2.wsops.CreatePrincipalRequestDocument; import org.brekka.xml.phalanx.v2.wsops.CreatePrincipalRequestDocument.CreatePrincipalRequest; import org.brekka.xml.phalanx.v2.wsops.CreatePrincipalResponseDocument; import org.brekka.xml.phalanx.v2.wsops.CreatePrincipalResponseDocument.CreatePrincipalResponse; import org.brekka.xml.phalanx.v2.wsops.DecryptKeyPairRequestDocument; import org.brekka.xml.phalanx.v2.wsops.DecryptKeyPairRequestDocument.DecryptKeyPairRequest; import org.brekka.xml.phalanx.v2.wsops.DecryptKeyPairResponseDocument; import org.brekka.xml.phalanx.v2.wsops.DecryptKeyPairResponseDocument.DecryptKeyPairResponse; import org.brekka.xml.phalanx.v2.wsops.DeleteCryptedDataRequestDocument; import org.brekka.xml.phalanx.v2.wsops.DeleteCryptedDataRequestDocument.DeleteCryptedDataRequest; import org.brekka.xml.phalanx.v2.wsops.DeleteCryptedDataResponseDocument; import org.brekka.xml.phalanx.v2.wsops.DeleteKeyPairRequestDocument; import org.brekka.xml.phalanx.v2.wsops.DeleteKeyPairRequestDocument.DeleteKeyPairRequest; import org.brekka.xml.phalanx.v2.wsops.DeleteKeyPairResponseDocument; import org.brekka.xml.phalanx.v2.wsops.DeletePrincipalRequestDocument; import org.brekka.xml.phalanx.v2.wsops.DeletePrincipalRequestDocument.DeletePrincipalRequest; import org.brekka.xml.phalanx.v2.wsops.DeletePrincipalResponseDocument; import org.brekka.xml.phalanx.v2.wsops.GenerateKeyPairRequestDocument; import org.brekka.xml.phalanx.v2.wsops.GenerateKeyPairRequestDocument.GenerateKeyPairRequest; import org.brekka.xml.phalanx.v2.wsops.GenerateKeyPairResponseDocument; import org.brekka.xml.phalanx.v2.wsops.GenerateKeyPairResponseDocument.GenerateKeyPairResponse; import org.brekka.xml.phalanx.v2.wsops.LogoutRequestDocument; import org.brekka.xml.phalanx.v2.wsops.LogoutRequestDocument.LogoutRequest; import org.brekka.xml.phalanx.v2.wsops.LogoutResponseDocument; import org.brekka.xml.phalanx.v2.wsops.PasswordBasedDecryptionRequestDocument; import org.brekka.xml.phalanx.v2.wsops.PasswordBasedDecryptionRequestDocument.PasswordBasedDecryptionRequest; import org.brekka.xml.phalanx.v2.wsops.PasswordBasedDecryptionResponseDocument; import org.brekka.xml.phalanx.v2.wsops.PasswordBasedDecryptionResponseDocument.PasswordBasedDecryptionResponse; import org.brekka.xml.phalanx.v2.wsops.PasswordBasedEncryptionRequestDocument; import org.brekka.xml.phalanx.v2.wsops.PasswordBasedEncryptionRequestDocument.PasswordBasedEncryptionRequest; import org.brekka.xml.phalanx.v2.wsops.PasswordBasedEncryptionResponseDocument; import org.brekka.xml.phalanx.v2.wsops.PasswordBasedEncryptionResponseDocument.PasswordBasedEncryptionResponse; import org.brekka.xml.phalanx.v2.wsops.PrincipalAssertedRequest; import org.brekka.xml.phalanx.v2.wsops.RetrievePublicKeyRequestDocument; import org.brekka.xml.phalanx.v2.wsops.RetrievePublicKeyRequestDocument.RetrievePublicKeyRequest; import org.brekka.xml.phalanx.v2.wsops.RetrievePublicKeyResponseDocument; import org.brekka.xml.phalanx.v2.wsops.RetrievePublicKeyResponseDocument.RetrievePublicKeyResponse; import org.brekka.xml.phalanx.v2.wsops.RetrievePublicKeyResponseDocument.RetrievePublicKeyResponse.PublicKey; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ws.server.endpoint.annotation.Endpoint; import org.springframework.ws.server.endpoint.annotation.PayloadRoot; import org.springframework.ws.server.endpoint.annotation.RequestPayload; import org.springframework.ws.server.endpoint.annotation.ResponsePayload; @Endpoint public class PhalanxEndpoint { private static final String NS = "http://brekka.org/xml/phalanx/v2/wsops"; @Autowired private PhalanxService phalanxService; @Autowired private PhalanxSessionService sessionService; @PayloadRoot(localPart = "AuthenticateRequest", namespace = NS) @ResponsePayload public AuthenticateResponseDocument authenticate(@RequestPayload AuthenticateRequestDocument requestDocument) { AuthenticateResponseDocument responseDocument = AuthenticateResponseDocument.Factory.newInstance(); AuthenticateResponse response = responseDocument.addNewAuthenticateResponse(); AuthenticateRequest request = requestDocument.getAuthenticateRequest(); AuthenticatedPrincipal authenticatedPrincipal = phalanxService .authenticate(id(request.getPrincipal().xgetId()), request.getPassword()); try { byte[] sessionId = sessionService.allocateAndBind(authenticatedPrincipal); byte[] privateKeyTokenId = sessionService .registerPrivateKey(authenticatedPrincipal.getDefaultPrivateKey()); AuthenticatedPrincipalType authenticatedPrincipalXml = response.addNewAuthenticatedPrincipal(); authenticatedPrincipalXml.setId(id(authenticatedPrincipal.getPrincipal().getId())); authenticatedPrincipalXml.setDefaultPrivateKey(privateKeyTokenId); authenticatedPrincipalXml.setSessionID(sessionId); authenticatedPrincipalXml.addNewDefaultKeyPair() .setId(id(authenticatedPrincipal.getPrincipal().getDefaultKeyPair().getId())); } finally { sessionService.unbind(); } return responseDocument; } @PayloadRoot(localPart = "LogoutRequest", namespace = NS) @ResponsePayload public LogoutResponseDocument asymmetricEncryption(@RequestPayload LogoutRequestDocument requestDocument) { LogoutRequest request = requestDocument.getLogoutRequest(); sessionService.logout(request.getSessionID()); LogoutResponseDocument responseDocument = LogoutResponseDocument.Factory.newInstance(); responseDocument.addNewLogoutResponse(); return responseDocument; } @PayloadRoot(localPart = "AsymmetricEncryptionRequest", namespace = NS) @ResponsePayload public AsymmetricEncryptionResponseDocument asymmetricEncryption( @RequestPayload AsymmetricEncryptionRequestDocument requestDocument) { AsymmetricEncryptionRequest request = requestDocument.getAsymmetricEncryptionRequest(); CryptedData cryptedData; if (request.isSetKeyPair()) { cryptedData = phalanxService.asymEncrypt(request.getData(), id(request.getKeyPair().xgetId())); } else if (request.isSetRecipient()) { cryptedData = phalanxService.asymEncrypt(request.getData(), id(request.getRecipient().xgetId())); } else { throw new IllegalStateException("Invalid XML, one of KeyPair or Recipient must be set"); } AsymmetricEncryptionResponseDocument responseDocument = AsymmetricEncryptionResponseDocument.Factory .newInstance(); AsymmetricEncryptionResponse response = responseDocument.addNewAsymmetricEncryptionResponse(); response.addNewCryptedData().setId(id(cryptedData.getId())); return responseDocument; } @PayloadRoot(localPart = "AsymmetricDecryptionRequest", namespace = NS) @ResponsePayload public AsymmetricDecryptionResponseDocument asymmetricDecryption( @RequestPayload AsymmetricDecryptionRequestDocument requestDocument) { AsymmetricDecryptionRequest request = requestDocument.getAsymmetricDecryptionRequest(); return doInSession(request, new SessionCallback<AsymmetricDecryptionRequest, AsymmetricDecryptionResponseDocument>() { @Override public AsymmetricDecryptionResponseDocument inSession(AsymmetricDecryptionRequest request) { AsymmetricDecryptionResponseDocument responseDocument = AsymmetricDecryptionResponseDocument.Factory .newInstance(); AsymmetricDecryptionResponse response = responseDocument .addNewAsymmetricDecryptionResponse(); PrivateKeyToken privateKeyToken = sessionService .retrievePrivateKey(request.getPrivateKey()); byte[] data = phalanxService.asymDecrypt(id(request.getCryptedData().xgetId()), privateKeyToken); response.setData(data); return responseDocument; } }); } @PayloadRoot(localPart = "PasswordBasedEncryptionRequest", namespace = NS) @ResponsePayload public PasswordBasedEncryptionResponseDocument passwordBasedEncryption( @RequestPayload PasswordBasedEncryptionRequestDocument requestDocument) { PasswordBasedEncryptionRequest request = requestDocument.getPasswordBasedEncryptionRequest(); CryptedData cryptoData = phalanxService.pbeEncrypt(request.getData(), request.getPassword()); PasswordBasedEncryptionResponseDocument responseDocument = PasswordBasedEncryptionResponseDocument.Factory .newInstance(); PasswordBasedEncryptionResponse response = responseDocument.addNewPasswordBasedEncryptionResponse(); response.addNewCryptedData().setId(id(cryptoData.getId())); return responseDocument; } @PayloadRoot(localPart = "PasswordBasedDecryptionRequest", namespace = NS) @ResponsePayload public PasswordBasedDecryptionResponseDocument passwordBasedDecryption( @RequestPayload PasswordBasedDecryptionRequestDocument requestDocument) { PasswordBasedDecryptionRequest request = requestDocument.getPasswordBasedDecryptionRequest(); byte[] data = phalanxService.pbeDecrypt(id(request.getCryptedData().xgetId()), request.getPassword()); PasswordBasedDecryptionResponseDocument responseDocument = PasswordBasedDecryptionResponseDocument.Factory .newInstance(); PasswordBasedDecryptionResponse response = responseDocument.addNewPasswordBasedDecryptionResponse(); response.setData(data); return responseDocument; } @PayloadRoot(localPart = "DecryptKeyPairRequest", namespace = NS) @ResponsePayload public DecryptKeyPairResponseDocument decryptKeyPair( @RequestPayload DecryptKeyPairRequestDocument requestDocument) { DecryptKeyPairRequest request = requestDocument.getDecryptKeyPairRequest(); return doInSession(request, new SessionCallback<DecryptKeyPairRequest, DecryptKeyPairResponseDocument>() { @Override public DecryptKeyPairResponseDocument inSession(DecryptKeyPairRequest request) { DecryptKeyPairResponseDocument responseDocument = DecryptKeyPairResponseDocument.Factory .newInstance(); DecryptKeyPairResponse response = responseDocument.addNewDecryptKeyPairResponse(); PrivateKeyToken privateKeyToken = sessionService.retrievePrivateKey(request.getPrivateKey()); PrivateKeyToken decryptedPrivateKeyToken = phalanxService .decryptKeyPair(id(request.getKeyPair().xgetId()), privateKeyToken); byte[] registeredPrivateKey = sessionService.registerPrivateKey(decryptedPrivateKeyToken); response.setPrivateKey(registeredPrivateKey); return responseDocument; } }); } @PayloadRoot(localPart = "GenerateKeyPairRequest", namespace = NS) @ResponsePayload public GenerateKeyPairResponseDocument generateKeyPair( @RequestPayload GenerateKeyPairRequestDocument requestDocument) { GenerateKeyPairRequest request = requestDocument.getGenerateKeyPairRequest(); KeyPair keyPair; if (request.isSetOwner()) { keyPair = phalanxService.generateKeyPair(id(request.getKeyPair().xgetId()), id(request.getOwner().xgetId())); } else { keyPair = phalanxService.generateKeyPair(id(request.getKeyPair().xgetId())); } GenerateKeyPairResponseDocument responseDocument = GenerateKeyPairResponseDocument.Factory.newInstance(); GenerateKeyPairResponse response = responseDocument.addNewGenerateKeyPairResponse(); response.addNewKeyPair().setId(id(keyPair.getId())); return responseDocument; } @PayloadRoot(localPart = "AssignKeyPairRequest", namespace = NS) @ResponsePayload public AssignKeyPairResponseDocument assignKeyPair( @RequestPayload AssignKeyPairRequestDocument requestDocument) { AssignKeyPairRequest request = requestDocument.getAssignKeyPairRequest(); return doInSession(request, new SessionCallback<AssignKeyPairRequest, AssignKeyPairResponseDocument>() { @Override public AssignKeyPairResponseDocument inSession(AssignKeyPairRequest request) { AssignKeyPairResponseDocument responseDocument = AssignKeyPairResponseDocument.Factory .newInstance(); AssignKeyPairResponse response = responseDocument.addNewAssignKeyPairResponse(); PrivateKeyToken privateKeyToken = sessionService.retrievePrivateKey(request.getPrivateKey()); KeyPair keyPair; if (request.isSetAssignToPrincipal()) { keyPair = phalanxService.assignKeyPair(privateKeyToken, id(request.getAssignToPrincipal().xgetId())); } else if (request.isSetAssignToKeyPair()) { keyPair = phalanxService.assignKeyPair(privateKeyToken, id(request.getAssignToKeyPair().xgetId())); } else { throw new IllegalStateException( "Invalid XML, one of AssignToKeyPair or AssignToPrincipal must be set"); } response.addNewKeyPair().setId(id(keyPair.getId())); return responseDocument; } }); } @PayloadRoot(localPart = "CloneKeyPairPublicRequest", namespace = NS) @ResponsePayload public CloneKeyPairPublicResponseDocument cloneKeyPairPublic( @RequestPayload CloneKeyPairPublicRequestDocument requestDocument) { CloneKeyPairPublicRequest request = requestDocument.getCloneKeyPairPublicRequest(); CloneKeyPairPublicResponseDocument responseDocument = CloneKeyPairPublicResponseDocument.Factory .newInstance(); CloneKeyPairPublicResponse response = responseDocument.addNewCloneKeyPairPublicResponse(); KeyPair keyPair = phalanxService.cloneKeyPairPublic(id(request.getKeyPair().xgetId())); response.addNewKeyPair().setId(id(keyPair.getId())); return responseDocument; } @PayloadRoot(localPart = "RetrievePublicKeyRequest", namespace = NS) @ResponsePayload public RetrievePublicKeyResponseDocument RetrievePublicKey( @RequestPayload RetrievePublicKeyRequestDocument requestDocument) { RetrievePublicKeyRequest request = requestDocument.getRetrievePublicKeyRequest(); RetrievePublicKeyResponseDocument responseDocument = RetrievePublicKeyResponseDocument.Factory .newInstance(); RetrievePublicKeyResponse response = responseDocument.addNewRetrievePublicKeyResponse(); ExportedPublicKey exportedPublicKey; if (request.isSetKeyPair()) { exportedPublicKey = phalanxService.retrievePublicKey(id(request.getKeyPair().xgetId())); } else if (request.isSetPrincipal()) { exportedPublicKey = phalanxService.retrievePublicKey(id(request.getPrincipal().xgetId())); } else { throw new IllegalStateException("Invalid XML, one of KeyPair or Principal must be set"); } PublicKey publicKey = response.addNewPublicKey(); publicKey.setEncoded(exportedPublicKey.getEncoded()); publicKey.setProfile(exportedPublicKey.getCryptoProfile()); return responseDocument; } @PayloadRoot(localPart = "DeleteCryptedDataRequest", namespace = NS) @ResponsePayload public DeleteCryptedDataResponseDocument deleteCryptedData( @RequestPayload DeleteCryptedDataRequestDocument requestDocument) { DeleteCryptedDataRequest request = requestDocument.getDeleteCryptedDataRequest(); DeleteCryptedDataResponseDocument responseDocument = DeleteCryptedDataResponseDocument.Factory .newInstance(); responseDocument.addNewDeleteCryptedDataResponse(); phalanxService.deleteCryptedData(id(request.getCryptedData().xgetId())); return responseDocument; } @PayloadRoot(localPart = "DeleteKeyPairRequest", namespace = NS) @ResponsePayload public DeleteKeyPairResponseDocument deleteKeyPair( @RequestPayload DeleteKeyPairRequestDocument requestDocument) { DeleteKeyPairRequest request = requestDocument.getDeleteKeyPairRequest(); DeleteKeyPairResponseDocument responseDocument = DeleteKeyPairResponseDocument.Factory.newInstance(); responseDocument.addNewDeleteKeyPairResponse(); phalanxService.deleteKeyPair(id(request.getKeyPair().xgetId())); return responseDocument; } @PayloadRoot(localPart = "CreatePrincipalRequest", namespace = NS) @ResponsePayload public CreatePrincipalResponseDocument createPrincipal( @RequestPayload CreatePrincipalRequestDocument requestDocument) { CreatePrincipalRequest request = requestDocument.getCreatePrincipalRequest(); CreatePrincipalResponseDocument responseDocument = CreatePrincipalResponseDocument.Factory.newInstance(); CreatePrincipalResponse response = responseDocument.addNewCreatePrincipalResponse(); Principal principal = phalanxService.createPrincipal(request.getPassword()); PrincipalType principalXml = response.addNewPrincipal(); principalXml.setId(id(principal.getId())); principalXml.addNewDefaultKeyPair().setId(id(principal.getDefaultKeyPair().getId())); return responseDocument; } @PayloadRoot(localPart = "DeletePrincipalRequest", namespace = NS) @ResponsePayload public DeletePrincipalResponseDocument deletePrincipal( @RequestPayload DeletePrincipalRequestDocument requestDocument) { DeletePrincipalRequest request = requestDocument.getDeletePrincipalRequest(); DeletePrincipalResponseDocument responseDocument = DeletePrincipalResponseDocument.Factory.newInstance(); responseDocument.addNewDeletePrincipalResponse(); phalanxService.deletePrincipal(id(request.getPrincipal().xgetId())); return responseDocument; } @PayloadRoot(localPart = "ChangePasswordRequest", namespace = NS) @ResponsePayload public ChangePasswordResponseDocument changePassword( @RequestPayload ChangePasswordRequestDocument requestDocument) { ChangePasswordRequest request = requestDocument.getChangePasswordRequest(); AuthenticatedPrincipal principal = sessionService.getCurrentPrincipal(); phalanxService.changePassword(principal.getPrincipal(), request.getCurrentPassword(), request.getNewPassword()); ChangePasswordResponseDocument responseDocument = ChangePasswordResponseDocument.Factory.newInstance(); responseDocument.addNewChangePasswordResponse(); return responseDocument; } protected <Req extends PrincipalAssertedRequest, ResDoc extends XmlObject> ResDoc doInSession(Req request, SessionCallback<Req, ResDoc> operation) { try { sessionService.bind(request.getSessionID()); return operation.inSession(request); } finally { sessionService.unbind(); } } protected static UUID uuid(UUIDType uuidType) { return UUID.fromString(uuidType.getStringValue()); } protected static IdentityKeyPair id(KeyPairIdType keyPairId) { return new IdentityKeyPair(uuid(keyPairId)); } protected static IdentityPrincipal id(PrincipalIdType principalId) { return new IdentityPrincipal(uuid(principalId)); } protected static IdentityCryptedData id(CryptedDataIdType cryptedDataId) { return new IdentityCryptedData(uuid(cryptedDataId)); } protected static String id(UUID id) { return id.toString(); } interface SessionCallback<Request, ResponseDocument> { ResponseDocument inSession(Request request); } }