Skip to content

Commit

Permalink
Merge branch 'master' of github.com:Azure/azure-sdk-for-java
Browse files Browse the repository at this point in the history
  • Loading branch information
jianghaolu committed Sep 25, 2016
2 parents 72d2485 + db083bb commit 9a099e2
Show file tree
Hide file tree
Showing 21 changed files with 733 additions and 117 deletions.
12 changes: 12 additions & 0 deletions azure-keyvault-webkey/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,22 @@
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.google.common.base.Objects;

/**
* As of http://tools.ietf.org/html/draft-ietf-jose-json-web-key-18.
Expand Down Expand Up @@ -401,7 +408,7 @@ public String toString() {
*/
private RSAPublicKeySpec getRSAPublicKeySpec() {

return new RSAPublicKeySpec(toBigInteger(n()), toBigInteger(e()));
return new RSAPublicKeySpec(toBigInteger(n), toBigInteger(e));
}

/**
Expand All @@ -411,8 +418,8 @@ private RSAPublicKeySpec getRSAPublicKeySpec() {
*/
private RSAPrivateKeySpec getRSAPrivateKeySpec() {

return new RSAPrivateCrtKeySpec(toBigInteger(n()), toBigInteger(e()), toBigInteger(d()), toBigInteger(p()),
toBigInteger(q()), toBigInteger(dp()), toBigInteger(dq()), toBigInteger(qi()));
return new RSAPrivateCrtKeySpec(toBigInteger(n), toBigInteger(e), toBigInteger(d), toBigInteger(p),
toBigInteger(q), toBigInteger(dp), toBigInteger(dq), toBigInteger(qi));
}

/**
Expand Down Expand Up @@ -455,7 +462,7 @@ private PrivateKey getRSAPrivateKey(Provider provider) {
* Verifies if the key is an RSA key.
*/
private void checkRSACompatible() {
if (!JsonWebKeyType.RSA.equals(kty()) && !JsonWebKeyType.RSA_HSM.equals(kty())) {
if (!JsonWebKeyType.RSA.equals(kty) && !JsonWebKeyType.RSA_HSM.equals(kty)) {
throw new UnsupportedOperationException("Not an RSA key");
}
}
Expand Down Expand Up @@ -557,4 +564,250 @@ public KeyPair toRSA(boolean includePrivateParameters, Provider provider) {
return new KeyPair(getRSAPublicKey(provider), null);
}
}

/**
* Converts AES key to JSON web key.
* @param secretKey AES key
* @return the JSON web key, converted from AES key.
*/
public static JsonWebKey fromAes(SecretKey secretKey) {
if (secretKey == null) {
return null;
}

return new JsonWebKey()
.withK(secretKey.getEncoded())
.withKty(JsonWebKeyType.OCT);
}

/**
* Converts JSON web key to AES key.
* @return AES key
*/
public SecretKey toAes() {
if (k == null) {
return null;
}

SecretKey secretKey = new SecretKeySpec(k, "AES");
return secretKey;
}

@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof JsonWebKey) {
return this.equals((JsonWebKey) obj);
}
return super.equals(obj);
}

/**
* Indicates whether some other {@link JsonWebKey} is "equal to" this one.
* @param jwk the other {@link JsonWebKey} to compare with.
* @return true if this {@link JsonWebKey} is the same as the jwk argument; false otherwise.
*/
public boolean equals(JsonWebKey jwk) {
if (jwk == null) {
return false;
}

if (!Objects.equal(kid, jwk.kid)) {
return false;
}

if (!Objects.equal(kty, jwk.kty)) {
return false;
}

if (!Objects.equal(keyOps, jwk.keyOps)) {
return false;
}

if (!Arrays.equals(k, jwk.k)) {
return false;
}

// Public parameters
if (!Arrays.equals(n, jwk.n)) {
return false;
}
if (!Arrays.equals(e, jwk.e)) {
return false;
}

// Private parameters
if (!Arrays.equals(d, jwk.d)) {
return false;
}
if (!Arrays.equals(dp, jwk.dp)) {
return false;
}
if (!Arrays.equals(dq, jwk.dq)) {
return false;
}
if (!Arrays.equals(qi, jwk.qi)) {
return false;
}
if (!Arrays.equals(p, jwk.p)) {
return false;
}
if (!Arrays.equals(q, jwk.q)) {
return false;
}

// HSM token
if (!Arrays.equals(t, jwk.t)) {
return false;
}

return true;
}

/**
* Verifies whether the {@link JsonWebKey} has private key.
* @return true if the {@link JsonWebKey} has private key; false otherwise.
*/
public boolean hasPrivateKey() {

if (JsonWebKeyType.OCT.equals(kty)) {
return k != null;
}

else if (JsonWebKeyType.RSA.equals(kty) || JsonWebKeyType.RSA_HSM.equals(kty)) {
return (d != null && dp != null && dq != null && qi != null && p != null && q != null);
}

return false;
}

/**
* Verifies whether the {@link JsonWebKey} is valid.
* @return true if the {@link JsonWebKey} is valid; false otherwise.
*/
@JsonIgnore
public boolean isValid() {
if (kty == null) {
return false;
}

if (keyOps != null) {
final Set<JsonWebKeyOperation> set = new HashSet<JsonWebKeyOperation>(JsonWebKeyOperation.ALL_OPERATIONS);
for (int i = 0; i < keyOps.size(); i++) {
if (!set.contains(keyOps.get(i))) {
return false;
}
}
}

if (JsonWebKeyType.OCT.equals(kty)) {
return isValidOctet();
}

else if (JsonWebKeyType.RSA.equals(kty)) {
return isValidRsa();
}

else if (JsonWebKeyType.RSA_HSM.equals(kty)) {
return isValidRsaHsm();
}
return false;
}

private boolean isValidOctet() {
if (k != null) {
return true;
}
return false;
}

private boolean isValidRsa() {
if (n == null || e == null) {
return false;
}

return hasPrivateKey()
|| (d == null && dp == null && dq == null && qi == null && p == null && q == null);
}

private boolean isValidRsaHsm() {
// MAY have public key parameters
if ((n == null && e != null) || (n != null && e == null)) {
return false;
}

// no private key
if (hasPrivateKey()) {
return false;
}

// MUST have ( T || ( N && E ) )
boolean tokenParameters = t != null;
boolean publicParameters = (n != null && e != null);

if (tokenParameters && publicParameters) {
return false;
}

return (tokenParameters || publicParameters);
}

/**
* Clear key materials.
*/
public void clearMemory() {
zeroArray(k); k = null;
zeroArray(n); n = null;
zeroArray(e); e = null;
zeroArray(d); d = null;
zeroArray(dp); dp = null;
zeroArray(dq); dq = null;
zeroArray(qi); qi = null;
zeroArray(p); p = null;
zeroArray(q); q = null;
zeroArray(t); t = null;
}

private static void zeroArray(byte[] bytes) {
if (bytes != null) {
Arrays.fill(bytes, (byte) 0);
}
}

@Override
public int hashCode() {
int hashCode = 48313; // setting it to a random prime number
if (kid != null) {
hashCode += kid.hashCode();
}

if (JsonWebKeyType.OCT.equals(kty)) {
hashCode += hashCode(k);
}

else if (JsonWebKeyType.RSA.equals(kty)) {
hashCode += hashCode(n);
}

else if (JsonWebKeyType.RSA_HSM.equals(kty)) {
hashCode += hashCode(t);
}

return hashCode;
}

private static int hashCode(byte[] obj) {
int hashCode = 0;

if (obj == null || obj.length == 0) {
return 0;
}

for (int i = 0; i < obj.length; i++) {
hashCode = (hashCode << 3) | (hashCode >> 29) ^ obj[i];
}
return hashCode;
}
}
Loading

0 comments on commit 9a099e2

Please sign in to comment.