Skip to content
This repository was archived by the owner on Oct 12, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 23 additions & 35 deletions azure-keyvault-cryptography/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-keyvault-parent</artifactId>
<version>1.1-beta-1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<parent>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-keyvault-parent</artifactId>
<version>1.1-beta-1</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>azure-keyvault-cryptography</artifactId>
<packaging>jar</packaging>
Expand Down Expand Up @@ -39,39 +39,27 @@
<checkstyle.skip>true</checkstyle.skip>
</properties>


<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<scope>test</scope>
<version>1.59</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-keyvault-webkey</artifactId>
<version>1.1-beta-1</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-keyvault-core</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<scope>test</scope>
<version>1.59</version>
</dependency>
<dependency>
<groupId>com.microsoft.rest</groupId>
<artifactId>client-runtime</artifactId>
<version>1.3.0</version>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-keyvault-webkey</artifactId>
<version>1.1-beta-1</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-client-authentication</artifactId>
<version>1.3.0</version>
<artifactId>azure-keyvault-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>

</dependencies>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@
import com.microsoft.azure.keyvault.cryptography.algorithms.Es256;
import com.microsoft.azure.keyvault.cryptography.algorithms.Es384;
import com.microsoft.azure.keyvault.cryptography.algorithms.Es512;
import com.microsoft.azure.keyvault.cryptography.algorithms.Ps256;
import com.microsoft.azure.keyvault.cryptography.algorithms.Ps384;
import com.microsoft.azure.keyvault.cryptography.algorithms.Ps512;
import com.microsoft.azure.keyvault.cryptography.algorithms.Rs256;
import com.microsoft.azure.keyvault.cryptography.algorithms.Rsa15;
import com.microsoft.azure.keyvault.cryptography.algorithms.RsaOaep;
import com.microsoft.azure.keyvault.cryptography.algorithms.RsaesOaep256;
import com.microsoft.azure.keyvault.cryptography.algorithms.PsBase;

public class AlgorithmResolver {

Expand All @@ -45,8 +50,13 @@ public class AlgorithmResolver {

Default.put(Rsa15.ALGORITHM_NAME, new Rsa15());
Default.put(RsaOaep.ALGORITHM_NAME, new RsaOaep());
Default.put(RsaesOaep256.ALGORITHM_NAME, new RsaesOaep256());

Default.put( Rs256.ALGORITHM_NAME, new Rs256() );
Default.put( Ps256.ALGORITHM_NAME, new Ps256());
Default.put( Ps384.ALGORITHM_NAME, new Ps384());
Default.put( Ps512.ALGORITHM_NAME, new Ps512());

// Default.put( RsNull.ALGORITHM_NAME, new RsNull() );

Default.put(Ecdsa256.ALGORITHM_NAME, new Ecdsa256());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.microsoft.azure.keyvault.core.IKey;
import com.microsoft.azure.keyvault.cryptography.algorithms.Rs256;
import com.microsoft.azure.keyvault.cryptography.algorithms.RsaOaep;
import com.microsoft.azure.keyvault.cryptography.algorithms.RsaSignature;
import com.microsoft.azure.keyvault.webkey.JsonWebKey;

public class RsaKey implements IKey {
Expand Down Expand Up @@ -346,12 +347,12 @@ public ListenableFuture<Pair<byte[], String>> signAsync(final byte[] digest, fin
throw new NoSuchAlgorithmException(algorithm);
}

Rs256 algo = (Rs256)baseAlgorithm;
RsaSignature algo = (RsaSignature) baseAlgorithm;

ISignatureTransform signer = algo.createSignatureTransform(_keyPair);

try {
return Futures.immediateFuture(Pair.of(signer.sign(digest), Rs256.ALGORITHM_NAME));
return Futures.immediateFuture(Pair.of(signer.sign(digest), algorithm));
} catch (Exception e) {
return Futures.immediateFailedFuture(e);
}
Expand All @@ -376,7 +377,7 @@ public ListenableFuture<Boolean> verifyAsync(final byte[] digest, final byte[] s
throw new NoSuchAlgorithmException(algorithm);
}

Rs256 algo = (Rs256)baseAlgorithm;
RsaSignature algo = (RsaSignature) baseAlgorithm;

ISignatureTransform signer = algo.createSignatureTransform(_keyPair);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.microsoft.azure.keyvault.cryptography.algorithms;

import java.security.KeyPair;

import com.microsoft.azure.keyvault.cryptography.ISignatureTransform;

public class Ps256 extends PsBase {

public final static String ALGORITHM_NAME = "PS256";
public final static String DIGEST_HASH_NAME = "SHA-256";

public Ps256() {
super(ALGORITHM_NAME);
}

@Override
public ISignatureTransform createSignatureTransform(KeyPair keyPair) {
return createSignatureTransform(keyPair, DIGEST_HASH_NAME);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.microsoft.azure.keyvault.cryptography.algorithms;

import java.security.KeyPair;

import com.microsoft.azure.keyvault.cryptography.ISignatureTransform;

public class Ps384 extends PsBase {

public final static String ALGORITHM_NAME = "PS384";
public final static String DIGEST_HASH_NAME = "SHA-384";

public Ps384() {
super(ALGORITHM_NAME);
}

@Override
public ISignatureTransform createSignatureTransform(KeyPair keyPair) {
return createSignatureTransform(keyPair, DIGEST_HASH_NAME);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.microsoft.azure.keyvault.cryptography.algorithms;

import java.security.KeyPair;

import com.microsoft.azure.keyvault.cryptography.ISignatureTransform;

public class Ps512 extends PsBase {
public final static String ALGORITHM_NAME = "PS512";
public final static String DIGEST_HASH_NAME = "SHA-512";

public Ps512() {
super(ALGORITHM_NAME);
}

@Override
public ISignatureTransform createSignatureTransform(KeyPair keyPair) {
return createSignatureTransform(keyPair, DIGEST_HASH_NAME);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for
* license information.
*/

package com.microsoft.azure.keyvault.cryptography.algorithms;

import java.math.BigInteger;
import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PSSParameterSpec;
import java.util.Arrays;
import java.util.zip.DataFormatException;
import java.security.Signature;

import com.microsoft.azure.keyvault.cryptography.ByteExtensions;
import com.microsoft.azure.keyvault.cryptography.ISignatureTransform;

/**
*
*/
public abstract class PsBase extends RsaSignature {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest RsaPssSignature as the name for this class.


protected PsBase(String name) {
super(name);
}

class PsBaseSignatureTransform implements ISignatureTransform {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And RsaPssSignatureTransform for this one :-)


private final KeyPair _keyPair;
private final int _emLen;
private final int _modBits;
private final String _digestName;

PsBaseSignatureTransform(KeyPair keyPair, String digestName) {
_keyPair = keyPair;
BigInteger modulus = ((RSAPublicKey) _keyPair.getPublic()).getModulus();
_emLen = getOctetLength(modulus.bitLength());
_modBits = ((RSAPublicKey) _keyPair.getPublic()).getModulus().bitLength();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modulus was already extracted above, so _modBits is just modulus.bitLength(). And that was used in getOctetLength as well. So an opportunity to condense this a bit.

_digestName = digestName;
}

@Override
public byte[] sign(byte[] digest) throws NoSuchAlgorithmException {

if (_keyPair.getPrivate() == null) {
throw new IllegalArgumentException("Keypair must have private key to for signing.");
}

// Construct the encoded message
// Apply the EMSA-PSS encoding operation (Section
// 9.1.1) to the message M to produce an encoded message EM of length
// \ceil ((modBits - 1)/8) octets such that the bit length of the
// integer OS2IP (EM) (see Section 4.2) is at most modBits - 1, where
// modBits is the length in bits of the RSA modulus n:
MessageDigest messageDigest = MessageDigest.getInstance(_digestName);
byte[] EM = EMSA_PSS_ENCODE_HASH(digest, _modBits - 1, messageDigest);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't EMSA_PSS_ENCODE use emBits rather than modBits? Where emBits would be emLen / 8?


// Convert to integer message
BigInteger m = OS2IP(EM);

// RSASP1(s)
m = RSASP1((RSAPrivateKey) _keyPair.getPrivate(), m);

// Convert to octet sequence
return I2OSP(m, _emLen);
}

@Override
public boolean verify(byte[] digest, byte[] signature) throws NoSuchAlgorithmException {

if (signature.length != _emLen) {
throw new IllegalArgumentException("invalid signature length");
}

// Convert to integer signature
BigInteger s = OS2IP(signature);

// Convert integer message
BigInteger m = RSAVP1((RSAPublicKey) _keyPair.getPublic(), s);

byte[] EM = I2OSP(m, _emLen);

MessageDigest messageDigest = MessageDigest.getInstance(_digestName);
return EMSA_PSS_VERIFY(digest, EM, _modBits, messageDigest);
Copy link

@schaabs schaabs Jun 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_modBits [](start = 47, length = 8)

_modBits-1

  1. EMSA-PSS verification: Apply the EMSA-PSS verification operation
    (Section 9.1.2) to the message M and the encoded message EM to
    determine whether they are consistent:

    Result = EMSA-PSS-VERIFY (M, EM, modBits - 1).

Copy link
Contributor

@herveyw-msft herveyw-msft Jun 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EMSA-PSS-VERIFY is actually supposed to use emBits, not modBits. emBits is the bit length of EM, and in the ctor of we call getOctetLength to get _emLen which is the octet length of EM. In theory, emBits should always be the same as _emLen / 8.

emBits and emLen are defined in https://tools.ietf.org/html/rfc3447#section-2

}

}

public ISignatureTransform createSignatureTransform(KeyPair keyPair, String digestString) {
return new PsBaseSignatureTransform(keyPair, digestString);
}
}
Loading