/** * Method that verifies an incoming signature and returns the response as application/xml. * * @param signatureVerificationRequest the request which is converted to a {@link * SignatureVerificationRequest} from xml * @return the {@link SignatureVerificationResponse} as application/xml */ @POST @Path("/verifySignature") @Consumes("application/xml") @Produces("application/xml") public SignatureVerificationResponse verifySignature( SignatureVerificationRequest signatureVerificationRequest) { SignatureVerificationResponse response = new SignatureVerificationResponse(); response.setCertificateInfos(new CertificateInfos()); boolean verified = false; String message = null; try { SignatureFormat format = signatureVerificationRequest.getSignatureFormat(); if (SignatureFormat.XMLDIGSIG.equals(format)) { try { SignatureData signatureData = getFromXmlDigSigSignature(signatureVerificationRequest, response); verified = super.verifySignature(signatureData); } catch (SignatureException e) { e.printStackTrace(); message = e.getMessage(); } } else if (SignatureFormat.CMS.equals(format)) { SignatureData signData = getFromCmsSignature(signatureVerificationRequest, response); try { // Verify verified = super.verifySignature(signData); } catch (SignatureException e) { e.printStackTrace(); message = e.getMessage(); } } response.setStatus(verified ? SignatureStatus.SUCCESS : SignatureStatus.FAILURE); if (message != null) { response.setMessage(message); } } catch (IOException ex) { throw new WebApplicationException(ex, Response.Status.INTERNAL_SERVER_ERROR); } catch (MarshalException ex) { throw new WebApplicationException(ex, Response.Status.INTERNAL_SERVER_ERROR); } catch (ParserConfigurationException ex) { throw new WebApplicationException(ex, Response.Status.INTERNAL_SERVER_ERROR); } catch (SAXException ex) { throw new WebApplicationException(ex, Response.Status.INTERNAL_SERVER_ERROR); } catch (CMSException ex) { throw new WebApplicationException(ex, Response.Status.INTERNAL_SERVER_ERROR); } return response; }
public byte[] getSender() { try { if (sendAddress == null) { ECKey key = ECKey.signatureToKey(getRawHash(), getSignature().toBase64()); sendAddress = key.getAddress(); } return sendAddress; } catch (SignatureException e) { logger.error(e.getMessage(), e); } return null; }
public static X509IdentityToken createX509IdentityToken( EndpointDescription ep, byte[] serverNonce, Cert certificate, PrivateKey key, SignatureData signatureData) throws ServiceResultException { if (signatureData == null) throw new NullPointerException("signatureData must be defined (will be filled in)"); UserTokenPolicy policy = ep.findUserTokenPolicy(UserTokenType.Certificate); if (policy == null) throw new ServiceResultException( StatusCodes.Bad_IdentityTokenRejected, "Certificate UserTokenType is not supported"); X509IdentityToken token = new X509IdentityToken(policy.getPolicyId(), certificate.getEncoded()); String securityPolicyUri = policy.getSecurityPolicyUri(); if (securityPolicyUri == null) securityPolicyUri = ep.getSecurityPolicyUri(); SecurityPolicy securityPolicy = SecurityPolicy.getSecurityPolicy(securityPolicyUri); Cert serverCert = new Cert(ep.getServerCertificate()); if ((securityPolicy != null) && (serverCert != null)) try { // Create a Signature object and initialize it with the private // key Signature signature = Signature.getInstance( securityPolicy.getAsymmetricSignatureAlgorithm().getTransformation()); signature.initSign(key); signature.update(serverCert.getEncoded()); signature.update(serverNonce); signatureData.setSignature(signature.sign()); signatureData.setAlgorithm(securityPolicy.getAsymmetricSignatureAlgorithm().getUri()); } catch (NoSuchAlgorithmException e) { throw new ServiceResultException( StatusCodes.Bad_SecurityChecksFailed, "Signature generation failed: " + e.getMessage()); } catch (InvalidKeyException e) { // Server certificate does not have encrypt usage throw new ServiceResultException( StatusCodes.Bad_CertificateInvalid, "Server certificate in endpoint is invalid: " + e.getMessage()); } catch (SignatureException e) { throw new ServiceResultException( StatusCodes.Bad_SecurityChecksFailed, "Signature generation failed: " + e.getMessage()); } return token; }
@Test public void test() throws SymmetricKeyDecryptionException, SymmetricKeyEncryptionException { // Precondition: // Owner has pw-protected MasterKeystore containig MKey_sig and MKey_enc // Owner hat lesser protected DeviceKeystore containing at least one // DeviceKey DevKey_1_enc // Create Empty SharePartList assertNotNull(volume); // ShareMetaData shareMetaData = volume.createShareMetaData(alias, // mKey_sig_pub, mKey_sig, deviceAlias, devKey1_enc); ShareMetaData shareMetaData = null; try { shareMetaData = new ShareMetaData( new JDBCHelperNonRevokeable("jdbc:sqlite:" + dbName + File.separator), mKey_sig_pub); } catch (Exception e) { e.printStackTrace(); fail(e.getMessage()); } try { Field smdField = Volume.class.getDeclaredField("shareMetaData"); smdField.setAccessible(true); smdField.set(volume, shareMetaData); } catch (Exception e) { fail(e.getMessage()); } assertNotNull(shareMetaData); SharePartList spl = shareMetaData.initSharePartList(); assertEquals("SharePartList is not empty, although it should be", 0, spl.size()); // Sign SharePartList try { spl.sign(mKey_sig); assertTrue(CryptCore.verifySignature(spl, spl.getSignature(), mKey_sig_pub)); } catch (SignatureException e2) { fail(e2.getMessage()); } spl.add(mKey_sig_pub, alias); assertEquals("SharePartList is not empty, although it should be", 1, spl.size()); try { spl.sign(mKey_sig); assertTrue(CryptCore.verifySignature(spl, spl.getSignature(), mKey_sig_pub)); } catch (SignatureException e2) { fail(e2.getMessage()); } // get DevKeys for the Devices that the owner wants to enable for this // Volume // Put keys in dkList dkList.put(deviceAlias, devKey1_enc); assertEquals("DeviceKeyList should have 1 element", 1, dkList.size()); // Create and sign devicelist DeviceList dl = shareMetaData.createDeviceList(mKey_sig_pub, dkList); assertEquals( "ShareMetaData should have 1 DeviceList", 1, shareMetaData.getDeviceLists().values().size()); // Create symmetric ShareKey SecretKey sk = CryptCore.generateSymmetricKey(); assertNotNull(sk); // Encrypt sk for all deviceLists Collection<DeviceList> deviceLists = shareMetaData.getDeviceLists().values(); Collection<PublicKey> pubKeys = new LinkedList<PublicKey>(); for (DeviceList devList : deviceLists) { pubKeys.addAll(devList.getPublicKeys()); } assertEquals(1, pubKeys.size()); // fetch ShareKeyDB ShareKeyDB db = shareMetaData.getShareKeys(); assertNotNull(db); // add Encrypted Keys to db try { db.add(sk, pubKeys); } catch (SymmetricKeyEncryptionException e1) { fail(e1.getMessage()); } assertEquals(1, db.size()); try { db.sign(mKey_sig, alias); } catch (SignatureException e1) { fail(e1.getMessage()); } // Encrypt skOb for all deviceLists shareMetaData.addObfuscationKey(devKey1_enc, null, null); System.out.println("Making ShareMetaData persistent..."); try { dl.sign(mKey_sig, shareMetaData.shareKeys, shareMetaData.obfuscationKeys); assertTrue( SignatureHelper.verify( dl.getSignature(), mKey_sig_pub, dl, shareMetaData.shareKeys.get(dl.getPublicKeys()), shareMetaData.obfuscationKeys.get(dl.getPublicKeys()))); } catch (SignatureException | InvalidKeyException | NoSuchAlgorithmException | SerializationException e2) { fail(e2.getMessage()); } // make sharemetadata persistent try { shareMetaData.persist(); shareMetaData.persist(dl); } catch (Exception e) { fail(e.getMessage()); } System.out.println("Loading Volume..."); // load volume with sharemetadata try { Volume loadedVol = new Volume(dbName); ShareMetaData loadedSMD = loadedVol.loadShareMetaData(mKey_sig_pub); assertArrayEquals(shareMetaData.getSignature(), loadedSMD.getSignature()); System.out.println("DONE"); } catch (Exception e) { e.printStackTrace(System.err); fail(e.getMessage()); } }
/** * Performs test signatures for the specified keys or for all if "all" specified. * * @param keyStore Loaded keystore to read keys from * @param alias Alias of key to test or "all" to test all * @param authCode Key password (if used, ie for JKS only) * @param signatureProvider Provider for creating the signature * @return The results for each key found * @throws CryptoTokenOfflineException In case the key could not be used */ public static Collection<KeyTestResult> testKey( KeyStore keyStore, String alias, char[] authCode, String signatureProvider) throws CryptoTokenOfflineException { if (LOG.isDebugEnabled()) { LOG.debug("testKey for alias: " + alias); } final Collection<KeyTestResult> result = new LinkedList<KeyTestResult>(); try { final Enumeration<String> e = keyStore.aliases(); while (e.hasMoreElements()) { final String keyAlias = e.nextElement(); if (alias.equalsIgnoreCase(ICryptoToken.ALL_KEYS) || alias.equals(keyAlias)) { if (LOG.isDebugEnabled()) { LOG.debug("checking keyAlias: " + keyAlias); } if (keyStore.isKeyEntry(keyAlias)) { String status; String publicKeyHash = null; boolean success = false; try { final PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias, authCode); final Certificate entryCert = keyStore.getCertificate(keyAlias); if (entryCert != null) { final PublicKey publicKey = entryCert.getPublicKey(); publicKeyHash = createKeyHash(publicKey); testSignAndVerify(privateKey, publicKey, signatureProvider); success = true; status = ""; } else { status = "Not testing keys with alias " + keyAlias + ". No certificate exists."; } } catch (ClassCastException ce) { status = "Not testing keys with alias " + keyAlias + ". Not a private key."; } catch (InvalidKeyException ex) { LOG.error("Error testing key: " + keyAlias, ex); status = ex.getMessage(); } catch (KeyStoreException ex) { LOG.error("Error testing key: " + keyAlias, ex); status = ex.getMessage(); } catch (NoSuchAlgorithmException ex) { LOG.error("Error testing key: " + keyAlias, ex); status = ex.getMessage(); } catch (NoSuchProviderException ex) { LOG.error("Error testing key: " + keyAlias, ex); status = ex.getMessage(); } catch (SignatureException ex) { LOG.error("Error testing key: " + keyAlias, ex); status = ex.getMessage(); } catch (UnrecoverableKeyException ex) { LOG.error("Error testing key: " + keyAlias, ex); status = ex.getMessage(); } result.add(new KeyTestResult(keyAlias, success, status, publicKeyHash)); } } } } catch (KeyStoreException ex) { throw new CryptoTokenOfflineException(ex); } if (LOG.isDebugEnabled()) { LOG.debug("<testKey"); } return result; }
/** * Extract credentials from the request. * * @param req * @return credentials associated with the request. */ public Credentials getCredentials(HttpServletRequest req, HttpServletResponse response) { if (testing) { calls.add(new Object[] {"getCredentials", req, response}); return new SimpleCredentials("testing", "testing".toCharArray()); } Credentials cred = null; String userId = null; String sakaiTrustedHeader = req.getHeader("x-sakai-token"); if (trustedTokenEnabled && sakaiTrustedHeader != null && sakaiTrustedHeader.trim().length() > 0) { String host = req.getRemoteAddr(); if (!safeHostAddrSet.contains(host)) { LOG.warn("Ignoring Trusted Token request from {} ", host); } else { // we have a HMAC based token, we should see if it is valid against the key we // have // and if so create some credentials. String[] parts = sakaiTrustedHeader.split(";"); if (parts.length == 3) { try { String hash = parts[0]; String user = parts[1]; String timestamp = parts[2]; String hmac = Signature.calculateRFC2104HMAC(user + ";" + timestamp, sharedSecret); if (hmac.equals(hash)) { // the user is Ok, we will trust it. userId = user; cred = createCredentials(userId, TrustedTokenTypes.TRUSTED_TOKEN); } else { LOG.debug("HMAC Match Failed {} != {} ", hmac, hash); } } catch (SignatureException e) { LOG.warn( "Failed to validate server token : {} {} ", sakaiTrustedHeader, e.getMessage()); } } else { LOG.warn( "Illegal number of elements in trusted server token:{} {} ", sakaiTrustedHeader, parts.length); } } } if (userId == null) { if (usingSession) { HttpSession session = req.getSession(false); if (session != null) { Credentials testCredentials = (Credentials) session.getAttribute(SA_AUTHENTICATION_CREDENTIALS); if (testCredentials instanceof SimpleCredentials) { SimpleCredentials sc = (SimpleCredentials) testCredentials; Object o = sc.getAttribute(CA_AUTHENTICATION_USER); if (o instanceof TrustedUser) { TrustedUser tu = (TrustedUser) o; if (tu.getUser() != null) { userId = tu.getUser(); cred = testCredentials; } } } } else { cred = null; } } else { Cookie[] cookies = req.getCookies(); if (cookies != null) { for (Cookie c : cookies) { if (trustedAuthCookieName.equals(c.getName())) { if (secureCookie && !c.getSecure()) { continue; } String cookieValue = c.getValue(); String[] decodedToken = decodeCookie(c.getValue()); if (decodedToken != null) { userId = decodedToken[0]; String tokenType = decodedToken[1]; TokenTrustValidator ttv = registeredTypes.get(tokenType); if (ttv == null || ttv.isTrusted(req)) { LOG.debug("Token is valid and decoded to {} ", userId); cred = createCredentials(userId, tokenType); refreshToken(response, c.getValue(), userId, tokenType); break; } else { LOG.debug("Cookie cant be trusted for this request {} ", cookieValue); } } else { LOG.debug("Invalid Cookie {} ", cookieValue); clearCookie(response); } } } } } } if (userId != null) { LOG.debug("Trusted Authentication for {} with credentials {} ", userId, cred); } return cred; }
/** @deprecated */ private boolean doVerify(PublicKey key, Provider sigProvider) throws CMSException, NoSuchAlgorithmException { String digestName = CMSSignedHelper.INSTANCE.getDigestAlgName(this.getDigestAlgOID()); String encName = CMSSignedHelper.INSTANCE.getEncryptionAlgName(this.getEncryptionAlgOID()); String signatureName = digestName + "with" + encName; Signature sig = CMSSignedHelper.INSTANCE.getSignatureInstance(signatureName, sigProvider); MessageDigest digest = CMSSignedHelper.INSTANCE.getDigestInstance(digestName, sigProvider); // TODO [BJA-109] Note: PSSParameterSpec requires JDK1.4+ /* try { DERObjectIdentifier sigAlgOID = encryptionAlgorithm.getObjectId(); DEREncodable sigParams = this.encryptionAlgorithm.getParameters(); if (sigAlgOID.equals(PKCSObjectIdentifiers.id_RSASSA_PSS)) { // RFC 4056 // When the id-RSASSA-PSS algorithm identifier is used for a signature, // the AlgorithmIdentifier parameters field MUST contain RSASSA-PSS-params. if (sigParams == null) { throw new CMSException( "RSASSA-PSS signature must specify algorithm parameters"); } AlgorithmParameters params = AlgorithmParameters.getInstance( sigAlgOID.getId(), sig.getProvider().getName()); params.init(sigParams.getDERObject().getEncoded(), "ASN.1"); PSSParameterSpec spec = (PSSParameterSpec)params.getParameterSpec(PSSParameterSpec.class); sig.setParameter(spec); } else { // TODO Are there other signature algorithms that provide parameters? if (sigParams != null) { throw new CMSException("unrecognised signature parameters provided"); } } } catch (IOException e) { throw new CMSException("error encoding signature parameters.", e); } catch (InvalidAlgorithmParameterException e) { throw new CMSException("error setting signature parameters.", e); } catch (InvalidParameterSpecException e) { throw new CMSException("error processing signature parameters.", e); } */ try { if (digestCalculator != null) { resultDigest = digestCalculator.getDigest(); } else { if (content != null) { content.write(new DigOutputStream(digest)); } else if (signedAttributeSet == null) { // TODO Get rid of this exception and just treat content==null as empty not missing? throw new CMSException("data not encapsulated in signature - use detached constructor."); } resultDigest = digest.digest(); } } catch (IOException e) { throw new CMSException("can't process mime object to create signature.", e); } // RFC 3852 11.1 Check the content-type attribute is correct { DERObject validContentType = getSingleValuedSignedAttribute(CMSAttributes.contentType, "content-type"); if (validContentType == null) { if (!isCounterSignature && signedAttributeSet != null) { throw new CMSException( "The content-type attribute type MUST be present whenever signed attributes are present in signed-data"); } } else { if (isCounterSignature) { throw new CMSException( "[For counter signatures,] the signedAttributes field MUST NOT contain a content-type attribute"); } if (!(validContentType instanceof DERObjectIdentifier)) { throw new CMSException( "content-type attribute value not of ASN.1 type 'OBJECT IDENTIFIER'"); } DERObjectIdentifier signedContentType = (DERObjectIdentifier) validContentType; if (!signedContentType.equals(contentType)) { throw new CMSException("content-type attribute value does not match eContentType"); } } } // RFC 3852 11.2 Check the message-digest attribute is correct { DERObject validMessageDigest = getSingleValuedSignedAttribute(CMSAttributes.messageDigest, "message-digest"); if (validMessageDigest == null) { if (signedAttributeSet != null) { throw new CMSException( "the message-digest signed attribute type MUST be present when there are any signed attributes present"); } } else { if (!(validMessageDigest instanceof ASN1OctetString)) { throw new CMSException("message-digest attribute value not of ASN.1 type 'OCTET STRING'"); } ASN1OctetString signedMessageDigest = (ASN1OctetString) validMessageDigest; if (!Arrays.constantTimeAreEqual(resultDigest, signedMessageDigest.getOctets())) { throw new CMSSignerDigestMismatchException( "message-digest attribute value does not match calculated value"); } } } // RFC 3852 11.4 Validate countersignature attribute(s) { AttributeTable signedAttrTable = this.getSignedAttributes(); if (signedAttrTable != null && signedAttrTable.getAll(CMSAttributes.counterSignature).size() > 0) { throw new CMSException("A countersignature attribute MUST NOT be a signed attribute"); } AttributeTable unsignedAttrTable = this.getUnsignedAttributes(); if (unsignedAttrTable != null) { ASN1EncodableVector csAttrs = unsignedAttrTable.getAll(CMSAttributes.counterSignature); for (int i = 0; i < csAttrs.size(); ++i) { Attribute csAttr = (Attribute) csAttrs.get(i); if (csAttr.getAttrValues().size() < 1) { throw new CMSException( "A countersignature attribute MUST contain at least one AttributeValue"); } // Note: We don't recursively validate the countersignature value } } } try { sig.initVerify(key); if (signedAttributeSet == null) { if (digestCalculator != null) { // need to decrypt signature and check message bytes return verifyDigest(resultDigest, key, this.getSignature(), sigProvider); } else if (content != null) { // TODO Use raw signature of the hash value instead content.write(new SigOutputStream(sig)); } } else { sig.update(this.getEncodedSignedAttributes()); } return sig.verify(this.getSignature()); } catch (InvalidKeyException e) { throw new CMSException("key not appropriate to signature in message.", e); } catch (IOException e) { throw new CMSException("can't process mime object to create signature.", e); } catch (SignatureException e) { throw new CMSException("invalid signature format in message: " + e.getMessage(), e); } }