Scope of easymock should be test instead of provided. Will fix that later.
Sent from my HTC Desire Op 13 jul. 2011 16:28 schreef <[email protected]> het volgende: > Author: jasha > Date: Wed Jul 13 14:28:19 2011 > New Revision: 1146054 > > URL: http://svn.apache.org/viewvc?rev=1146054&view=rev > Log: > RAVE-85 start with storing/fetching oauth consumer keys in the database. Will continue next week. > > Added: > incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDb.java > incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/jpa/OAuthConsumerStoreDb.java > incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/ > incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/ > incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/ > incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbTest.java > incubator/rave/trunk/rave-shindig/src/test/resources/keys/ > incubator/rave/trunk/rave-shindig/src/test/resources/keys/oauthkey.pem > Removed: > incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/jpa/OAuthStoreConsumerIndexDb.java > incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/jpa/OAuthStoreConsumerKeyAndSecretDb.java > Modified: > incubator/rave/trunk/rave-shindig/pom.xml > incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/orm.xml > > Modified: incubator/rave/trunk/rave-shindig/pom.xml > URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/pom.xml?rev=1146054&r1=1146053&r2=1146054&view=diff > ============================================================================== > --- incubator/rave/trunk/rave-shindig/pom.xml (original) > +++ incubator/rave/trunk/rave-shindig/pom.xml Wed Jul 13 14:28:19 2011 > @@ -89,6 +89,17 @@ > <version>1.3</version> > <scope>test</scope> > </dependency> > + > + <dependency> > + <groupId>junit</groupId> > + <artifactId>junit</artifactId> > + <scope>test</scope> > + </dependency> > + <dependency> > + <groupId>org.easymock</groupId> > + <artifactId>easymock</artifactId> > + <scope>provided</scope> > + </dependency> > </dependencies> > > <build> > > Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDb.java > URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDb.java?rev=1146054&view=auto > ============================================================================== > --- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDb.java (added) > +++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDb.java Wed Jul 13 14:28:19 2011 > @@ -0,0 +1,177 @@ > +/* > + * Licensed to the Apache Software Foundation (ASF) under one > + * or more contributor license agreements. See the NOTICE file > + * distributed with this work for additional information > + * regarding copyright ownership. The ASF licenses this file > + * to you 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.apache.shindig.gadgets.oauth; > + > +import net.oauth.OAuth; > +import net.oauth.OAuthConsumer; > +import net.oauth.OAuthServiceProvider; > +import net.oauth.signature.RSA_SHA1; > +import org.apache.commons.collections.CollectionUtils; > +import org.apache.commons.io.IOUtils; > +import org.apache.commons.lang.StringUtils; > +import org.apache.rave.os.DatabasePopulateContextListener; > +import org.apache.shindig.auth.SecurityToken; > +import org.apache.shindig.gadgets.GadgetException; > +import org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb; > +import org.springframework.core.io.ClassPathResource; > + > +import javax.persistence.EntityManager; > +import javax.persistence.Query; > +import java.io.IOException; > +import java.io.InputStream; > +import java.util.List; > + > +/** > + * that retrieves the consumer_key, consumer_secret and key_type from the database > + * <p/> > + * Usage scenario: Rave OpenSocial container is the oauth consumer > + * (oauth data are stored elsewhere, this container tries to fetch data from e.g. Google) > + */ > +public class OAuthStoreDb implements OAuthStore { > + /** > + * This is the JPA entity manager, shared by all threads accessing this service (need to check > + * that its really thread safe). > + */ > + private EntityManager entityManager; > + > + /** > + * Callback to use when no per-key callback URL is found. > + */ > + private String defaultCallbackUrl; > + > + /* > + * Private key for signing the RSH_PRIVATE oauth requests > + */ > + private BasicOAuthStoreConsumerKeyAndSecret defaultKey; > + > + > + public OAuthStoreDb(String defaultCallbackUrl, > + String pathToPrivateKey, > + String privateKeyName) throws IOException { > + this(defaultCallbackUrl, pathToPrivateKey, privateKeyName, > + DatabasePopulateContextListener.getEntityManager()); > + } > + > + public OAuthStoreDb(String defaultCallbackUrl, > + String pathToPrivateKey, > + String privateKeyName, > + EntityManager entityManager) throws IOException { > + this.defaultCallbackUrl = defaultCallbackUrl; > + this.defaultKey = loadDefaultKey(pathToPrivateKey, privateKeyName); > + this.entityManager = entityManager; > + } > + > + @Override > + public ConsumerInfo getConsumerKeyAndSecret(SecurityToken securityToken, String serviceName, > + OAuthServiceProvider provider) > + throws GadgetException { > + String gadgetUri = securityToken.getAppUrl(); > + OAuthConsumerStoreDb consumerStoreDb = findOAuthConsumerStore(gadgetUri, serviceName); > + if (consumerStoreDb == null) { > + return null; > + } > + > + OAuthConsumer consumer = createOAuthConsumer(provider, consumerStoreDb); > + String callbackUrl = (consumerStoreDb.getCallbackUrl() != null ? > + consumerStoreDb.getCallbackUrl() : defaultCallbackUrl); > + > + return new ConsumerInfo(consumer, consumerStoreDb.getKeyName(), callbackUrl); > + } > + > + @Override > + public TokenInfo getTokenInfo(SecurityToken securityToken, ConsumerInfo consumerInfo, String serviceName, String tokenName) throws GadgetException { > + return null; //To change body of implemented methods use File | Settings | File Templates. > + } > + > + @Override > + public void setTokenInfo(SecurityToken securityToken, ConsumerInfo consumerInfo, String serviceName, String tokenName, TokenInfo tokenInfo) throws GadgetException { > + //To change body of implemented methods use File | Settings | File Templates. > + } > + > + @Override > + public void removeToken(SecurityToken securityToken, ConsumerInfo consumerInfo, String serviceName, String tokenName) throws GadgetException { > + //To change body of implemented methods use File | Settings | File Templates. > + } > + > + static BasicOAuthStoreConsumerKeyAndSecret loadDefaultKey( > + String signingKeyFile, String signingKeyName) throws IOException { > + InputStream inputStream = new ClassPathResource(signingKeyFile) > + .getInputStream(); > + String privateKey = IOUtils.toString(inputStream); > + privateKey = BasicOAuthStore.convertFromOpenSsl(privateKey); > + return new BasicOAuthStoreConsumerKeyAndSecret(null, privateKey, > + BasicOAuthStoreConsumerKeyAndSecret.KeyType.RSA_PRIVATE, signingKeyName, null); > + > + } > + > + /** > + * Creates an {@link OAuthConsumer} based on the OAuth signature method > + * > + * @param provider {@link net.oauth.OAuthServiceProvider} > + * @param consumerStoreDb {@link org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb} persistent OAuth consumer keys & secrets > + * @return {@link OAuthConsumer} if the signature method is supported > + */ > + private OAuthConsumer createOAuthConsumer(OAuthServiceProvider provider, > + OAuthConsumerStoreDb consumerStoreDb) { > + String consumerKey = consumerStoreDb.getConsumerKey(); > + String consumerSecret = consumerStoreDb.getConsumerSecret(); > + > + OAuthConsumer consumer; > + switch (consumerStoreDb.getKeyType()) { > + case RSA_PRIVATE: > + consumer = new OAuthConsumer(null, consumerKey, null, provider); > + // The oauth.net java code has lots of magic. By setting this property > + // here, code thousands of lines away knows that the consumerSecret > + // value in the consumer should be treated as > + // an RSA private key and not an HMAC key. > + consumer.setProperty(OAuth.OAUTH_SIGNATURE_METHOD, OAuth.RSA_SHA1); > + consumer.setProperty(RSA_SHA1.PRIVATE_KEY, defaultKey.getConsumerSecret()); > + break; > + case HMAC_SYMMETRIC: > + consumer = new OAuthConsumer(null, consumerKey, consumerSecret, provider); > + consumer.setProperty(OAuth.OAUTH_SIGNATURE_METHOD, OAuth.HMAC_SHA1); > + break; > + case PLAINTEXT: > + consumer = new OAuthConsumer(null, consumerKey, consumerSecret, provider); > + consumer.setProperty(OAuth.OAUTH_SIGNATURE_METHOD, "PLAINTEXT"); > + break; > + default: > + throw new IllegalArgumentException("Cannot handle keytype " + > + consumerStoreDb.getKeyType()); > + } > + return consumer; > + } > + > + OAuthConsumerStoreDb findOAuthConsumerStore(String gadgetUri, String serviceName) { > + if (StringUtils.isBlank(gadgetUri) || StringUtils.isBlank(serviceName)) { > + return null; > + } > + Query q = entityManager.createQuery("SELECT x FROM OAuthConsumerStoreDb x " + > + "WHERE x.gadgetUri = :gadgetUriParam and x.serviceName = :serviceNameParam"); > + q.setParameter("gadgetUriParam", gadgetUri).setParameter("serviceNameParam", serviceName); > + q.setFirstResult(0); > + q.setMaxResults(1); > + List<OAuthConsumerStoreDb> results = (List<OAuthConsumerStoreDb>) q.getResultList(); > + if (CollectionUtils.isEmpty(results)) { > + return null; > + } > + return results.get(0); > + } > +} > > Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/jpa/OAuthConsumerStoreDb.java > URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/jpa/OAuthConsumerStoreDb.java?rev=1146054&view=auto > ============================================================================== > --- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/jpa/OAuthConsumerStoreDb.java (added) > +++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/jpa/OAuthConsumerStoreDb.java Wed Jul 13 14:28:19 2011 > @@ -0,0 +1,185 @@ > +/* > + * Licensed to the Apache Software Foundation (ASF) under one > + * or more contributor license agreements. See the NOTICE file > + * distributed with this work for additional information > + * regarding copyright ownership. The ASF licenses this file > + * to you 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.apache.shindig.gadgets.oauth.jpa; > + > +import org.apache.shindig.social.opensocial.jpa.api.DbObject; > + > +import javax.persistence.Column; > +import javax.persistence.Entity; > +import javax.persistence.EnumType; > +import javax.persistence.Enumerated; > +import javax.persistence.GeneratedValue; > +import javax.persistence.Id; > +import javax.persistence.Table; > +import javax.persistence.UniqueConstraint; > + > +import static javax.persistence.GenerationType.IDENTITY; > + > +/** > + * Persistent store for OAuth consumer key & secrets. > + * Equivalent of: > + * <pre> > + * { > + * "http://localhost:8080/samplecontainer/examples/oauth.xml" : { > + * "" : { > + * "consumer_key" : "gadgetConsumer", > + * "consumer_secret" : "gadgetSecret", > + * "key_type" : "HMAC_SYMMETRIC" > + * } > + * }, > + * "http://localhost:8080/samplecontainer/examples/shindigoauth.xml" : { > + * "shindig" : { > + * "consumer_key" : " http://localhost:8080/samplecontainer/examples/shindigoauth.xml", > + * "consumer_secret" : "secret", > + * "key_type" : "HMAC_SYMMETRIC" > + * } > + * } > + * } > + * </pre> > + */ > +@Entity > +@Table(name = "oauth_consumer_store", > + uniqueConstraints = @UniqueConstraint(columnNames = {"gadget_uri", "service_name"})) > +public class OAuthConsumerStoreDb implements DbObject { > + > + /** > + * enum of KeyType's > + */ > + public static enum KeyType { > + HMAC_SYMMETRIC, RSA_PRIVATE, PLAINTEXT > + } > + > + @Id > + @GeneratedValue(strategy = IDENTITY) > + @Column(name = "oid") > + private long objectId; > + > + /** > + * URI where the gadget is hosted, e.g. http://www.example.com/mygadget.xml > + */ > + @Column(name = "gadget_uri", length = 512) > + private String gadgetUri; > + > + /** > + * Name of the oAuth service, matches /Module/ModulePrefs/OAuth/Service/@name > + * in a gadget definition > + */ > + @Column(name = "service_name") > + private String serviceName; > + > + > + /** > + * Value for oauth_consumer_key > + */ > + @Column(name = "consumer_key") > + private String consumerKey; > + > + /** > + * HMAC secret, or RSA private key, depending on KeyType > + */ > + @Column(name = "consumer_secret") > + private String consumerSecret; > + > + /** > + * Type of key, also known as "OAuth signature method" > + */ > + @Enumerated(value = EnumType.STRING) > + @Column(name = "key_type") > + private KeyType keyType; > + > + /** > + * Name of public key to use with xoauth_public_key parameter. > + * May be {@literal null}. > + */ > + @Column(name = "key_name") > + private String keyName; > + > + /** > + * Callback URL associated with this consumer key > + * May be {@literal null}. > + */ > + @Column(name = "callback_url") > + private String callbackUrl; > + > + > + /** > + * {@inheritDoc} > + */ > + @Override > + public long getObjectId() { > + return objectId; > + } > + > + public String getGadgetUri() { > + return gadgetUri; > + } > + > + public void setGadgetUri(String gadgetUri) { > + this.gadgetUri = gadgetUri; > + } > + > + public String getServiceName() { > + return serviceName; > + } > + > + public void setServiceName(String serviceName) { > + this.serviceName = serviceName; > + } > + > + public String getConsumerKey() { > + return consumerKey; > + } > + > + public void setConsumerKey(String consumerKey) { > + this.consumerKey = consumerKey; > + } > + > + public String getConsumerSecret() { > + return consumerSecret; > + } > + > + public void setConsumerSecret(String consumerSecret) { > + this.consumerSecret = consumerSecret; > + } > + > + public KeyType getKeyType() { > + return keyType; > + } > + > + public void setKeyType(KeyType keyType) { > + this.keyType = keyType; > + } > + > + public String getKeyName() { > + return keyName; > + } > + > + public void setKeyName(String keyName) { > + this.keyName = keyName; > + } > + > + public String getCallbackUrl() { > + return callbackUrl; > + } > + > + public void setCallbackUrl(String callbackUrl) { > + this.callbackUrl = callbackUrl; > + } > +} > > Modified: incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/orm.xml > URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/orm.xml?rev=1146054&r1=1146053&r2=1146054&view=diff > ============================================================================== > --- incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/orm.xml (original) > +++ incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/orm.xml Wed Jul 13 14:28:19 2011 > @@ -84,6 +84,5 @@ > </entity> > <entity class="org.apache.shindig.social.opensocial.jpa.ApplicationDataMapValueDb"> > </entity> > - <entity class="org.apache.shindig.gadgets.oauth.jpa.OAuthStoreConsumerIndexDb"/> > - <entity class="org.apache.shindig.gadgets.oauth.jpa.OAuthStoreConsumerKeyAndSecretDb"/> > + <entity class="org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb"/> > </entity-mappings> > > Added: incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbTest.java > URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbTest.java?rev=1146054&view=auto > ============================================================================== > --- incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbTest.java (added) > +++ incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbTest.java Wed Jul 13 14:28:19 2011 > @@ -0,0 +1,74 @@ > +/* > + * Licensed to the Apache Software Foundation (ASF) under one > + * or more contributor license agreements. See the NOTICE file > + * distributed with this work for additional information > + * regarding copyright ownership. The ASF licenses this file > + * to you 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.apache.shindig.gadgets.oauth; > + > +import net.oauth.OAuthServiceProvider; > +import org.apache.shindig.auth.SecurityToken; > +import org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb; > +import org.apache.shindig.social.core.oauth.OAuthSecurityToken; > +import org.junit.Test; > + > +import java.util.Date; > + > +import static org.junit.Assert.assertEquals; > +import static org.junit.Assert.assertNotNull; > +import static org.junit.Assert.assertNull; > + > +/** > + * Test class for {@link OAuthStoreDb} > + */ > +public class OAuthStoreDbTest { > + private static final long NEXT_HOUR = 1000L * 60L * 60L; > + @Test > + public void testGetConsumerKeyAndSecret() throws Exception { > + //String userId, String appUrl, String appId, String domain, > + //String container, Long expiresAt > + SecurityToken token = new OAuthSecurityToken("john.doe", " http://localhost:8080/myapp", > + "myapp", "localhost", "default", new Date().getTime() + NEXT_HOUR); > + String serviceName = "testService"; > + > + OAuthStoreDb oAuthStoreDb = new OAuthStoreDb("http://localhost:8080 ","keys/oauthkey.pem", > + "consumer-test-key"); > + > + OAuthConsumerStoreDb consumerStore = new OAuthConsumerStoreDb(); > + final String gadgetUri = " http://localhost:8080/samplecontainer/examples/oauth.xml"; > + consumerStore.setGadgetUri(gadgetUri); > + consumerStore.setConsumerKey("gadgetConsumer"); > + consumerStore.setConsumerSecret("gadgetSecret"); > + consumerStore.setKeyType(OAuthConsumerStoreDb.KeyType.HMAC_SYMMETRIC); > + > + OAuthServiceProvider provider = new OAuthServiceProvider(null, null, null); > + final OAuthStore.ConsumerInfo keyAndSecret = oAuthStoreDb.getConsumerKeyAndSecret(token, serviceName, provider); > + assertNull(keyAndSecret); > + > + > + } > + > + @Test > + public void testLoadDefaultKey() throws Exception { > + BasicOAuthStoreConsumerKeyAndSecret defaultKey = > + OAuthStoreDb.loadDefaultKey("keys/oauthkey.pem", "consumer-test-key"); > + assertNotNull("defaultKey", defaultKey); > + assertEquals(BasicOAuthStoreConsumerKeyAndSecret.KeyType.RSA_PRIVATE, defaultKey.getKeyType()); > + assertEquals("consumer-test-key", defaultKey.getKeyName()); > + final String keyFileContents = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANXjbMKL9N+9950V7QaDhr7JbF5uJtFgsiCsRjYDT9SaVCaNk2zXRXzqj2acKpAthV0R+4cVeWBN0mDL8CE/Rjo0r+9375DrSpi+jb+hnhYTGfiGbpJrUfCxlOXrvdsw4kZpLVKaj8wZFPb11Cnl5s1QBpPGWs1ij/qj/V04xRwXAgMBAAECgYEA0jXUPFgE8KjpZQ+Zhl9Z3MRlp2Em8XzRVF88GfWjTdXngoR+MehYuO5mxXgSNOUoP1JfHGI0ijux2cRVWrevMdO+0bkezMmgWlBTAqgoidwauX+0NyIRJOOG0anggmSrrf8jocjDLp7ZEhVjmtMzvys6P4RyFaNKXNyxK7J1/LECQQD/fB8vKvenzm9NNEdQyap3d0LYqWd/47NiOCCoS8K/DGVVIZiQQigUOi3ZTY6LV2Eb2RtwRnwBXMsKuQUTHZGDAkEA1lHU2OYGYP7SMu+fxzwFRNx0DrXWqIe0XFQX6EDRbk5H/eKgVt1tER8Mbin/z5utvXXiGJAj6+Eop6uqNPUq3QJAWbFZwVV0XJU8vf38i4BBOG/GKApRK7Tk5TaPQIZYeHoBmUGSLhMLvw4tynxP7tteXEh8OY6FOnU5UyphfbSDwQJBAIC0oesjsH79aMQ4DS77x3pEHdpbry6EWHb99WF/04W3sxovx/SCgyY+DBv4UuydZCgcLAxuO3RDQkP3Hn8xIG0CQQC9keRoDlA7RkwCXq76vEzLUqWiRSeHbXkaniSp7/xqzlw1IeMTtzoqMcJAulNr9W+vKKBYtE3sjXLcmO/CvWk/"; > + assertEquals(keyFileContents, defaultKey.getConsumerSecret()); > + } > +} > > Added: incubator/rave/trunk/rave-shindig/src/test/resources/keys/oauthkey.pem > URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/test/resources/keys/oauthkey.pem?rev=1146054&view=auto > ============================================================================== > --- incubator/rave/trunk/rave-shindig/src/test/resources/keys/oauthkey.pem (added) > +++ incubator/rave/trunk/rave-shindig/src/test/resources/keys/oauthkey.pem Wed Jul 13 14:28:19 2011 > @@ -0,0 +1,16 @@ > +-----BEGIN PRIVATE KEY----- > +MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANXjbMKL9N+9950V > +7QaDhr7JbF5uJtFgsiCsRjYDT9SaVCaNk2zXRXzqj2acKpAthV0R+4cVeWBN0mDL > +8CE/Rjo0r+9375DrSpi+jb+hnhYTGfiGbpJrUfCxlOXrvdsw4kZpLVKaj8wZFPb1 > +1Cnl5s1QBpPGWs1ij/qj/V04xRwXAgMBAAECgYEA0jXUPFgE8KjpZQ+Zhl9Z3MRl > +p2Em8XzRVF88GfWjTdXngoR+MehYuO5mxXgSNOUoP1JfHGI0ijux2cRVWrevMdO+ > +0bkezMmgWlBTAqgoidwauX+0NyIRJOOG0anggmSrrf8jocjDLp7ZEhVjmtMzvys6 > +P4RyFaNKXNyxK7J1/LECQQD/fB8vKvenzm9NNEdQyap3d0LYqWd/47NiOCCoS8K/ > +DGVVIZiQQigUOi3ZTY6LV2Eb2RtwRnwBXMsKuQUTHZGDAkEA1lHU2OYGYP7SMu+f > +xzwFRNx0DrXWqIe0XFQX6EDRbk5H/eKgVt1tER8Mbin/z5utvXXiGJAj6+Eop6uq > +NPUq3QJAWbFZwVV0XJU8vf38i4BBOG/GKApRK7Tk5TaPQIZYeHoBmUGSLhMLvw4t > +ynxP7tteXEh8OY6FOnU5UyphfbSDwQJBAIC0oesjsH79aMQ4DS77x3pEHdpbry6E > +WHb99WF/04W3sxovx/SCgyY+DBv4UuydZCgcLAxuO3RDQkP3Hn8xIG0CQQC9keRo > +DlA7RkwCXq76vEzLUqWiRSeHbXkaniSp7/xqzlw1IeMTtzoqMcJAulNr9W+vKKBY > +tE3sjXLcmO/CvWk/ > +-----END PRIVATE KEY----- > >
