1b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien/* 2b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * Copyright 2007 Google, Inc. 3b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 4b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * Licensed under the Apache License, Version 2.0 (the "License"); 5b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * you may not use this file except in compliance with the License. 6b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * You may obtain a copy of the License at 7b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 8b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * http://www.apache.org/licenses/LICENSE-2.0 9b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 10b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * Unless required by applicable law or agreed to in writing, software 11b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * distributed under the License is distributed on an "AS IS" BASIS, 12b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * See the License for the specific language governing permissions and 14b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * limitations under the License. 15b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien */ 16b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 17b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienpackage net.oauth.signature; 18b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 19b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.io.ByteArrayInputStream; 20b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.io.UnsupportedEncodingException; 21b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.security.GeneralSecurityException; 22b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.security.KeyFactory; 23b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.security.PrivateKey; 24b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.security.PublicKey; 25b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.security.Signature; 26b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.security.cert.CertificateFactory; 27b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.security.cert.X509Certificate; 28b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.security.spec.EncodedKeySpec; 29b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.security.spec.PKCS8EncodedKeySpec; 30b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.security.spec.X509EncodedKeySpec; 31b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 32b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport net.oauth.OAuth; 33b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport net.oauth.OAuthAccessor; 34b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport net.oauth.OAuthException; 35b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 36b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien/** 37b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * Class to handle RSA-SHA1 signatures on OAuth requests. A consumer 38b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * that wishes to use public-key signatures on messages does not need 39b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * a shared secret with the service provider, but it needs a private 40b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * RSA signing key. You create it like this: 41b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 42b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * OAuthConsumer c = new OAuthConsumer(callback_url, consumer_key, 43b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * null, provider); 44b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * c.setProperty(RSA_SHA1.PRIVATE_KEY, consumer_privateRSAKey); 45b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 46b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * consumer_privateRSAKey must be an RSA signing key and 47b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * of type java.security.PrivateKey, String, or byte[]. In the latter two 48b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * cases, the key must be PKCS#8-encoded (byte[]) or PKCS#8-encoded and 49b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * then Base64-encoded (String). 50b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 51b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * A service provider that wishes to verify signatures made by such a 52b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * consumer does not need a shared secret with the consumer, but it needs 53b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * to know the consumer's public key. You create the necessary 54b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * OAuthConsumer object (on the service provider's side) like this: 55b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 56b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * OAuthConsumer c = new OAuthConsumer(callback_url, consumer_key, 57b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * null, provider); 58b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * c.setProperty(RSA_SHA1.PUBLIC_KEY, consumer_publicRSAKey); 59b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 60b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * consumer_publicRSAKey must be the consumer's public RSAkey and 61b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * of type java.security.PublicKey, String, or byte[]. In the latter two 62b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * cases, the key must be X509-encoded (byte[]) or X509-encoded and 63b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * then Base64-encoded (String). 64b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 65b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * Alternatively, a service provider that wishes to verify signatures made 66b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * by such a consumer can use a X509 certificate containing the consumer's 67b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * public key. You create the necessary OAuthConsumer object (on the service 68b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * provider's side) like this: 69b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 70b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * OAuthConsumer c = new OAuthConsumer(callback_url, consumer_key, 71b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * null, provider); 72b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * c.setProperty(RSA_SHA1.X509_CERTIFICATE, consumer_cert); 73b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 74b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * consumer_cert must be a X509 Certificate containing the consumer's public 75b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * key and be of type java.security.cert.X509Certificate, String, 76b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * or byte[]. In the latter two cases, the certificate must be DER-encoded 77b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * (byte[]) or PEM-encoded (String). 78b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 79b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * @author Dirk Balfanz 80b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * @hide 81b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 82b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien */ 83b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienpublic class RSA_SHA1 extends OAuthSignatureMethod { 84b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 85b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien final static public String PRIVATE_KEY = "RSA-SHA1.PrivateKey"; 86b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien final static public String PUBLIC_KEY = "RSA-SHA1.PublicKey"; 87b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien final static public String X509_CERTIFICATE = "RSA-SHA1.X509Certificate"; 88b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 89b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private PrivateKey privateKey = null; 90b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private PublicKey publicKey = null; 91b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 92b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien @Override 93b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien protected void initialize(String name, OAuthAccessor accessor) 94b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throws OAuthException { 95b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien super.initialize(name, accessor); 96b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 97b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien Object privateKeyObject = accessor.consumer.getProperty(PRIVATE_KEY); 98b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien try { 99b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien if (privateKeyObject != null) { 100b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien if (privateKeyObject instanceof PrivateKey) { 101b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien privateKey = (PrivateKey)privateKeyObject; 102b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } else if (privateKeyObject instanceof String) { 103b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien privateKey = getPrivateKeyFromPem((String)privateKeyObject); 104b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } else if (privateKeyObject instanceof byte[]) { 105b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien privateKey = getPrivateKeyFromDer((byte[])privateKeyObject); 106b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } else { 107b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throw new IllegalArgumentException( 108b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien "Private key set through RSA_SHA1.PRIVATE_KEY must be of " + 109b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien "type PrivateKey, String, or byte[], and not " + 110b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien privateKeyObject.getClass().getName()); 111b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 112b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 113b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 114b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien Object publicKeyObject = accessor.consumer.getProperty(PUBLIC_KEY); 115b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien if (publicKeyObject != null) { 116b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien if (publicKeyObject instanceof PublicKey) { 117b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien publicKey = (PublicKey)publicKeyObject; 118b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } else if (publicKeyObject instanceof String) { 119b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien publicKey = getPublicKeyFromPem((String)publicKeyObject); 120b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } else if (publicKeyObject instanceof byte[]) { 121b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien publicKey = getPublicKeyFromDer((byte[])publicKeyObject); 122b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } else { 123b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throw new IllegalArgumentException( 124b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien "Public key set through RSA_SHA1.PRIVATE_KEY must be of " + 125b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien "type PublicKey, String, or byte[], and not " + 126b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien publicKeyObject.getClass().getName()); 127b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 128b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } else { // public key was null. perhaps they gave us a X509 cert. 129b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien Object certObject = accessor.consumer.getProperty(X509_CERTIFICATE); 130b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien if (certObject != null) { 131b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien if (certObject instanceof X509Certificate) { 132b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien publicKey = ((X509Certificate) certObject).getPublicKey(); 133b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } else if (certObject instanceof String) { 134b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien publicKey = getPublicKeyFromPemCert((String)certObject); 135b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } else if (certObject instanceof byte[]) { 136b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien publicKey = getPublicKeyFromDerCert((byte[])certObject); 137b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } else { 138b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throw new IllegalArgumentException( 139b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien "X509Certificate set through RSA_SHA1.X509_CERTIFICATE" + 140b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien " must be of type X509Certificate, String, or byte[]," + 141b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien " and not " + certObject.getClass().getName()); 142b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 143b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 144b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 145b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } catch (GeneralSecurityException e) { 146b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throw new OAuthException(e); 147b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 148b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 149b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 150b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private PublicKey getPublicKeyFromPemCert(String certObject) 151b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throws GeneralSecurityException { 152b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien CertificateFactory fac = CertificateFactory.getInstance("X509"); 153b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien ByteArrayInputStream in = new ByteArrayInputStream(certObject.getBytes()); 154b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien X509Certificate cert = (X509Certificate)fac.generateCertificate(in); 155b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien return cert.getPublicKey(); 156b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 157b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 158b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private PublicKey getPublicKeyFromDerCert(byte[] certObject) 159b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throws GeneralSecurityException { 160b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien CertificateFactory fac = CertificateFactory.getInstance("X509"); 161b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien ByteArrayInputStream in = new ByteArrayInputStream(certObject); 162b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien X509Certificate cert = (X509Certificate)fac.generateCertificate(in); 163b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien return cert.getPublicKey(); 164b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 165b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 166b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private PublicKey getPublicKeyFromDer(byte[] publicKeyObject) 167b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throws GeneralSecurityException { 168b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien KeyFactory fac = KeyFactory.getInstance("RSA"); 169b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKeyObject); 170b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien return fac.generatePublic(pubKeySpec); 171b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 172b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 173b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private PublicKey getPublicKeyFromPem(String publicKeyObject) 174b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throws GeneralSecurityException { 175b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien return getPublicKeyFromDer(decodeBase64(publicKeyObject)); 176b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 177b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 178b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private PrivateKey getPrivateKeyFromDer(byte[] privateKeyObject) 179b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throws GeneralSecurityException { 180b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien KeyFactory fac = KeyFactory.getInstance("RSA"); 181b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(privateKeyObject); 182b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien return fac.generatePrivate(privKeySpec); 183b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 184b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 185b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private PrivateKey getPrivateKeyFromPem(String privateKeyObject) 186b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throws GeneralSecurityException { 187b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien return getPrivateKeyFromDer(decodeBase64(privateKeyObject)); 188b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 189b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 190b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien @Override 191b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien protected String getSignature(String baseString) throws OAuthException { 192b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien try { 193b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien byte[] signature = sign(baseString.getBytes(OAuth.ENCODING)); 194b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien return base64Encode(signature); 195b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } catch (UnsupportedEncodingException e) { 196b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throw new OAuthException(e); 197b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } catch (GeneralSecurityException e) { 198b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throw new OAuthException(e); 199b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 200b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 201b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 202b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien @Override 203b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien protected boolean isValid(String signature, String baseString) 204b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throws OAuthException { 205b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien try { 206b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien return verify(decodeBase64(signature), 207b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien baseString.getBytes(OAuth.ENCODING)); 208b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } catch (UnsupportedEncodingException e) { 209b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throw new OAuthException(e); 210b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } catch (GeneralSecurityException e) { 211b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throw new OAuthException(e); 212b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 213b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 214b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 215b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private byte[] sign(byte[] message) throws GeneralSecurityException { 216b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien if (privateKey == null) { 217b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throw new IllegalStateException("need to set private key with " + 218b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien "OAuthConsumer.setProperty when " + 219b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien "generating RSA-SHA1 signatures."); 220b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 221b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien Signature signer = Signature.getInstance("SHA1withRSA"); 222b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien signer.initSign(privateKey); 223b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien signer.update(message); 224b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien return signer.sign(); 225b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 226b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 227b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private boolean verify(byte[] signature, byte[] message) 228b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throws GeneralSecurityException { 229b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien if (publicKey == null) { 230b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien throw new IllegalStateException("need to set public key with " + 231b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien " OAuthConsumer.setProperty when " + 232b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien "verifying RSA-SHA1 signatures."); 233b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 234b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien Signature verifier = Signature.getInstance("SHA1withRSA"); 235b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien verifier.initVerify(publicKey); 236b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien verifier.update(message); 237b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien return verifier.verify(signature); 238b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 239b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien} 240