From c070f5f27d8034f681b7fc9a43825cfc7fd6f06f Mon Sep 17 00:00:00 2001 From: ScottVonDuhn Date: Wed, 11 Aug 2021 18:44:01 -0400 Subject: [PATCH] feat: Add HMAC-SHA256 signature method for OAuth 1.0 (#711) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addы HMAC-SHA256 signature method for OAuth 1.0 --- .../auth/oauth/OAuthHmacSha256Signer.java | 64 +++++++++++++++++++ .../auth/oauth/OAuthHmacSha256SignerTest.java | 54 ++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 google-oauth-client/src/main/java/com/google/api/client/auth/oauth/OAuthHmacSha256Signer.java create mode 100644 google-oauth-client/src/test/java/com/google/api/client/auth/oauth/OAuthHmacSha256SignerTest.java diff --git a/google-oauth-client/src/main/java/com/google/api/client/auth/oauth/OAuthHmacSha256Signer.java b/google-oauth-client/src/main/java/com/google/api/client/auth/oauth/OAuthHmacSha256Signer.java new file mode 100644 index 000000000..f93360b46 --- /dev/null +++ b/google-oauth-client/src/main/java/com/google/api/client/auth/oauth/OAuthHmacSha256Signer.java @@ -0,0 +1,64 @@ +/* + * Copyright 2021 Google LLC + * + * 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 com.google.api.client.auth.oauth; + +import com.google.api.client.util.StringUtils; +import com.google.common.io.BaseEncoding; +import java.security.GeneralSecurityException; +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +/** OAuth {@code "HMAC-SHA256"} signature method. */ +public final class OAuthHmacSha256Signer implements OAuthSigner { + + /** Client secret */ + private final String clientSharedSecret; + + /** Token secret */ + private String tokenSharedSecret; + + public void setTokenSecret(String tokenSecret) { + tokenSharedSecret = tokenSecret; + } + + public OAuthHmacSha256Signer(String clientSecret) { + this.clientSharedSecret = clientSecret; + } + + @Override + public String getSignatureMethod() { + return "HMAC-SHA256"; + } + + @Override + public String computeSignature(String signatureBaseString) throws GeneralSecurityException { + // compute key + StringBuilder keyBuffer = new StringBuilder(); + if (clientSharedSecret != null) { + keyBuffer.append(OAuthParameters.escape(clientSharedSecret)); + } + keyBuffer.append('&'); + if (tokenSharedSecret != null) { + keyBuffer.append(OAuthParameters.escape(tokenSharedSecret)); + } + String key = keyBuffer.toString(); + // sign + SecretKey secretKey = new SecretKeySpec(StringUtils.getBytesUtf8(key), "HmacSHA256"); + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(secretKey); + return BaseEncoding.base64().encode(mac.doFinal(StringUtils.getBytesUtf8(signatureBaseString))); + } +} diff --git a/google-oauth-client/src/test/java/com/google/api/client/auth/oauth/OAuthHmacSha256SignerTest.java b/google-oauth-client/src/test/java/com/google/api/client/auth/oauth/OAuthHmacSha256SignerTest.java new file mode 100644 index 000000000..eed0592cc --- /dev/null +++ b/google-oauth-client/src/test/java/com/google/api/client/auth/oauth/OAuthHmacSha256SignerTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2021 Google LLC + * + * 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 com.google.api.client.auth.oauth; + +import static org.junit.Assert.assertEquals; + +import java.security.GeneralSecurityException; +import org.junit.Test; + +/** Tests {@link OAuthHmacSha256Signer}. */ +public class OAuthHmacSha256SignerTest { + + @Test + public void testComputeSignatureWithNullSecrets() throws GeneralSecurityException { + OAuthHmacSha256Signer signer = new OAuthHmacSha256Signer(null); + String expectedSignature = "l/Es58FI4BtBciSH9XtY/5jXFee70v7/rPiQgEpvv00="; + assertEquals(expectedSignature, signer.computeSignature("baseString")); + } + + @Test + public void testComputeSignatureWithNullClientSecret() throws GeneralSecurityException { + OAuthHmacSha256Signer signer = new OAuthHmacSha256Signer(null); + signer.setTokenSecret("tokenSecret"); + String expectedSignature = "PgNWY2qQ53qvk3WySct/f037/usxMGpNDjmJeISmgCM="; + assertEquals(expectedSignature, signer.computeSignature("baseString")); + } + + @Test + public void testComputeSignatureWithNullTokenSecret() throws GeneralSecurityException { + OAuthHmacSha256Signer signer = new OAuthHmacSha256Signer("clientSecret"); + String expectedSignature = "cNrT2sqgyQ+dd7rbAhYBFBk8o82/yZyZkavqsfMDqpo="; + assertEquals(expectedSignature, signer.computeSignature("baseString")); + } + + @Test + public void testComputeSignature() throws GeneralSecurityException { + OAuthHmacSha256Signer signer = new OAuthHmacSha256Signer("clientSecret"); + signer.setTokenSecret("tokenSecret"); + String expectedSignature = "sfnrBcfwccOs2mpc60VQ5zXx5ReP/46lgUcBhU2a4PM="; + assertEquals(expectedSignature, signer.computeSignature("baseString")); + } +}