pax_global_header 0000666 0000000 0000000 00000000064 13535653744 0014531 g ustar 00root root 0000000 0000000 52 comment=779351d5a5d74a8f886da42190b4948c80735cbe
scram-2.1/ 0000775 0000000 0000000 00000000000 13535653744 0012500 5 ustar 00root root 0000000 0000000 scram-2.1/.gitignore 0000664 0000000 0000000 00000000151 13535653744 0014465 0 ustar 00root root 0000000 0000000 .idea/
target/
*.iml
nbactions.xml
nb-configuration.xml
/bin/
.project
.classpath
.settings/
hs_err*.log
scram-2.1/.gitlab-ci.yml 0000664 0000000 0000000 00000000476 13535653744 0015143 0 ustar 00root root 0000000 0000000 image: openjdk:8-stretch
stages:
- build
variables:
M2_HOME: ".m2/maven"
MAVEN_OPTS: "-Dmaven.repo.local=.m2"
build:
stage: build
cache:
paths:
- .m2/
script:
- bash mvnw clean verify -P safer
build-oracle-jdk-7:
extends: build
image: registry.gitlab.com/ongresinc/scram/oracle-jdk:7
scram-2.1/.mvn/ 0000775 0000000 0000000 00000000000 13535653744 0013356 5 ustar 00root root 0000000 0000000 scram-2.1/.mvn/wrapper/ 0000775 0000000 0000000 00000000000 13535653744 0015036 5 ustar 00root root 0000000 0000000 scram-2.1/.mvn/wrapper/MavenWrapperDownloader.java 0000664 0000000 0000000 00000011531 13535653744 0022330 0 ustar 00root root 0000000 0000000 /*
* Copyright 2007-present the original author or authors.
*
* 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.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.5";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
final String username = System.getenv("MVNW_USERNAME");
final char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}
scram-2.1/.mvn/wrapper/maven-wrapper.properties 0000664 0000000 0000000 00000000332 13535653744 0021736 0 ustar 00root root 0000000 0000000 distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
scram-2.1/CHANGELOG 0000664 0000000 0000000 00000000770 13535653744 0013716 0 ustar 00root root 0000000 0000000 # 2.1
* Updated saslprep to version 1.1 to remove a build dependency coming from stringprep module
# 2.0
* Out of beta testing
# 2.0-beta3
* Fixed licenses issues
# 2.0-beta2
* Added saslprep tests
# 2.0-beta1
* Add new dependency StringPrep
# 1.9-beta1
* API change to be compatible with Java 7
* Added standard SASLPrep
* Failover to bouncy castle implementation of PBKDF2WithHmacSHA256 to support Oracle JDK 7
# 1.0.0-beta.2
* Fix maven issue and javadoc
# 1.0.0-beta.1
* First version
scram-2.1/LICENSE 0000664 0000000 0000000 00000002355 13535653744 0013512 0 ustar 00root root 0000000 0000000 Copyright 2017, OnGres.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
scram-2.1/NOTICE 0000664 0000000 0000000 00000002517 13535653744 0013411 0 ustar 00root root 0000000 0000000 This source code includes source code from other projects. Below the list
of the project were the source code has been copied together with the
path of the copied source files, their license, their notice (if any)
and the modification that have been done.
1. saslprep
Dependency SaslPrep is used from project stringprep developed by various authors (https://gitlab.com/ongresinc/stringprep)
and licensed under the BSD 2-Clause "Simplified" License (see thirdparty/saslprep-LICENSE).
2. Tests of SaslPrep
File common/src/test/java/com/ongres/scram/common/stringprep/ScramFunctionsTest contains tests
from project passlib_lambda developed by davidchua (https://github.com/davidchua/passlib_lambda)
and licensed under the MIT license (see thirdparty/passlib_lambda-LICENSE).
The source has been modified to be included under the Java package
com.ongres.scram.common.ScramFunctionsTest and to only include used parts.
3. bouncy castle
All Java source files included into folder common/src/main/java/com/ongres/scram/common/bouncycastle
are copied from project bouncy castle developed by various authors (https://www.bouncycastle.org/)
and licensed under the bouncy castle license (see thirdparty/bouncycastle-LICENSE).
The source has been modified to be included under the Java package com.ongres.scram.common.bouncycastle
and to only include used parts.
scram-2.1/README.md 0000664 0000000 0000000 00000004236 13535653744 0013764 0 ustar 00root root 0000000 0000000 # SCRAM Java Implementation
## Overview
SCRAM (Salted Challenge Response Authentication Mechanism) is part of the family
of Simple Authentication and Security Layer
([SASL, RFC 4422](https://tools.ietf.org/html/rfc4422)) authentication
mechanisms.
It is described as part of [RFC 5802](https://tools.ietf.org/html/rfc5802) and
[RFC7677](https://tools.ietf.org/html/rfc7677).
This project will serve for the basis of
[PostgreSQL's](https://www.postgresql.org) [JDBC](https://jdbc.postgresql.org/)
driver SCRAM support (coming in PostgreSQL 10).
The code is licensed under the BSD "Simplified 2 Clause" license (see [LICENSE](LICENSE)).
## Goals
This project aims to provide a complete clean-room implementation of SCRAM. It
is written in Java and provided in a modular, re-usable way, independent of
other software or programs.
Current functionality includes:
* [Common infrastructure](common) for building both client and server SCRAM implementations.
* A [Client API](client) for using SCRAM as a client.
* Support for both SHA-1 and SHA-256.
* Basic support for channel binding.
* No runtime external dependencies.
* Well tested (+75 tests).
Current limitations:
* Server API and integration tests will be added soon.
## How to use the client API
Please read [Client's README.md](client).
Javadoc: [](http://javadoc.io/doc/com.ongres.scram/client)
## Common API
'common' is the module that contains code common to both client and server SCRAM projects.
If you with to develop either a client or server API, you may very well build on top of this
API. Import maven dependency:
com.ongres.scramcommon
and check the Javadoc: [](http://javadoc.io/doc/com.ongres.scram/common)
## Contributing
Please submit [Merge Requests](https://gitlab.com/ongresinc/scram) for code contributions.
Make sure to compile with `mvn -Psafer` before submitting a MR.
Releases (on the master branch only) must be verified with:
mvn -Psafer -Pmaster-branch
scram-2.1/client/ 0000775 0000000 0000000 00000000000 13535653744 0013756 5 ustar 00root root 0000000 0000000 scram-2.1/client/README.md 0000664 0000000 0000000 00000007033 13535653744 0015240 0 ustar 00root root 0000000 0000000 # SCRAM Client API
[](http://javadoc.io/doc/com.ongres.scram/client)
For general description, please refer to [the main README.md](https://gitlab.com/ongresinc/scram).
## How to use the client API
1. Add Maven (or equivalent) dependencies :
```xml
com.ongres.scramclientVERSION
```
2. Get a ```ScramClient```. A ```ScramClient``` can be configured with several parameters,
and matches a given server. From the client, several ```ScramSession```s can be created,
for potentially different users. Under certain conditions (read Javadoc) it is thread safe.
A simple example could be:
```java
ScramClient scramClient = ScramClient
.channelBinding(ChannelBinding.NO)
.stringPreparation(NO_PREPARATION)
.serverMechanisms("SCRAM-SHA-1")
.setup();
```
More configuration methods and options are available, as shown below:
```java
ScramClient scramClient = ScramClient
.channelBinding(ChannelBinding.YES)
.stringPreparation(NO_PREPARATION)
.serverMechanisms("SCRAM-SHA-1", "SCRAM-SHA-1-PLUS", "SCRAM-SHA-256", "SCRAM-SHA-256-PLUS")
.nonceSupplier(() -> generateNonce())
.secureRandomAlgorithmProvider("algorithm", "provider")
.setup();
```
3. For each authentication round and/or user, create a ```ScramSession``` and get the client-first-message:
```java
ScramSession scramSession = scramClient.scramSession("user");
scramSession.clientFirstMessage()
```
4. Receive the server-first-message:
```java
ScramSession.ServerFirstProcessor serverFirst = scramSession.receiveServerFirstMessage(message);
// Read the salt and iterations:
serverFirst.getSalt()
serverFirst.getIteration()
```
5. Generate the client-last-message:
```java
ScramSession.ClientFinalProcessor clientFinal = serverFirst.finalMessagesHandler("password");
clientFinal.clientFinalMessage()
```
6. Receive the server-last-message, check if is valid or error, etc:
```java
ScramSession.ServerFinalProcessor serverFinal = clientFinal.receiveServerFinalMessage(message);
// Methods to check if it is error, get error, verify signature
serverFinal.isError()
serverFinal.getErrorMessage()
serverFinal.verifyServerSignature()
```
## Example
The following example runs a full SCRAM session, using the RFC's data as an example.
```java
ScramClient scramClient = ScramClient
.channelBinding(ScramClient.ChannelBinding.NO)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertised("SCRAM-SHA-1")
.nonceSupplier(() -> "fyko+d2lbbFgONRv9qkxdawL")
.setup();
ScramSession scramSession = scramClient.scramSession("user");
System.out.println(scramSession.clientFirstMessage());
ScramSession.ServerFirstProcessor serverFirstProcessor = scramSession.receiveServerFirstMessage(
"r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096"
);
System.out.println("Salt: " + serverFirstProcessor.getSalt() + ", i: " + serverFirstProcessor.getIteration());
ScramSession.ClientFinalProcessor clientFinalProcessor
= serverFirstProcessor.clientFinalProcessor("pencil");
System.out.println(clientFinalProcessor.clientFinalMessage());
ScramSession.ServerFinalProcessor serverFinalProcessor
= clientFinalProcessor.receiveServerFinalMessage("v=rmF9pqV8S7suAoZWja4dJRkFsKQ=");
if(serverFinalProcessor.isError()) {
// throw authentication exception
}
System.out.println(serverFinalProcessor.verifyServerSignature());
```
scram-2.1/client/pom.xml 0000664 0000000 0000000 00000007476 13535653744 0015311 0 ustar 00root root 0000000 0000000
4.0.0parentcom.ongres.scram2.1clientSCRAM - clientcom.ongres.scramcommon${project.version}junitjunittestcom.ongres.scramcommon${project.version}testtest-jarjavadoc.io-links!maven.javadoc.skiporg.apache.maven.pluginsmaven-dependency-plugin2.8unpack-javadocpackageunpack${project.groupId}commonjavadoc${project.version}false${project.build.directory}/common-javadocorg.apache.maven.pluginsmaven-javadoc-pluginhttp://static.javadoc.io/${project.groupId}/common/${project.version}${project.build.directory}/common-javadoc
scram-2.1/client/src/ 0000775 0000000 0000000 00000000000 13535653744 0014545 5 ustar 00root root 0000000 0000000 scram-2.1/client/src/main/ 0000775 0000000 0000000 00000000000 13535653744 0015471 5 ustar 00root root 0000000 0000000 scram-2.1/client/src/main/java/ 0000775 0000000 0000000 00000000000 13535653744 0016412 5 ustar 00root root 0000000 0000000 scram-2.1/client/src/main/java/com/ 0000775 0000000 0000000 00000000000 13535653744 0017170 5 ustar 00root root 0000000 0000000 scram-2.1/client/src/main/java/com/ongres/ 0000775 0000000 0000000 00000000000 13535653744 0020465 5 ustar 00root root 0000000 0000000 scram-2.1/client/src/main/java/com/ongres/scram/ 0000775 0000000 0000000 00000000000 13535653744 0021572 5 ustar 00root root 0000000 0000000 scram-2.1/client/src/main/java/com/ongres/scram/client/ 0000775 0000000 0000000 00000000000 13535653744 0023050 5 ustar 00root root 0000000 0000000 scram-2.1/client/src/main/java/com/ongres/scram/client/NonceSupplier.java 0000664 0000000 0000000 00000002601 13535653744 0026500 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.client;
public interface NonceSupplier {
String get();
}
scram-2.1/client/src/main/java/com/ongres/scram/client/ScramClient.java 0000664 0000000 0000000 00000043551 13535653744 0026127 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.client;
import com.ongres.scram.common.ScramMechanism;
import com.ongres.scram.common.ScramMechanisms;
import com.ongres.scram.common.gssapi.Gs2CbindFlag;
import com.ongres.scram.common.stringprep.StringPreparation;
import com.ongres.scram.common.util.CryptoUtil;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import static com.ongres.scram.common.util.Preconditions.*;
/**
* A class that can be parametrized to generate {@link ScramSession}s.
* This class supports the channel binding and string preparation mechanisms that are provided by module scram-common.
*
* The class is fully configurable, including options to selected the desired channel binding,
* automatically pick the best client SCRAM mechanism based on those supported (advertised) by the server,
* selecting an externally-provided SecureRandom instance or an external nonceProvider, or choosing the nonce length.
*
* This class is thread-safe if the two following conditions are met:
*
*
The SecureRandom used ({@link SecureRandom} by default) are thread-safe too.
* The contract of {@link java.util.Random} marks it as thread-safe, so inherited classes are also expected
* to maintain it.
*
*
No external nonceSupplier is provided; or if provided, it is thread-safe.
*
* So this class, once instantiated via the {@link Builder#setup()}} method, can serve for multiple users and
* authentications.
*/
public class ScramClient {
/**
* Length (in characters, bytes) of the nonce generated by default (if no nonce supplier is provided)
*/
public static final int DEFAULT_NONCE_LENGTH = 24;
/**
* Select whether this client will support channel binding or not
*/
public enum ChannelBinding {
/**
* Don't use channel binding. Server must support at least one non-channel binding mechanism.
*/
NO(Gs2CbindFlag.CLIENT_NOT),
/**
* Force use of channel binding. Server must support at least one channel binding mechanism.
* Channel binding data will need to be provided as part of the ClientFirstMessage.
*/
YES(Gs2CbindFlag.CHANNEL_BINDING_REQUIRED),
/**
* Channel binding is preferred. Non-channel binding mechanisms will be used if either the server does not
* support channel binding, or no channel binding data is provided as part of the ClientFirstMessage
*/
IF_SERVER_SUPPORTS_IT(Gs2CbindFlag.CLIENT_YES_SERVER_NOT)
;
private final Gs2CbindFlag gs2CbindFlag;
ChannelBinding(Gs2CbindFlag gs2CbindFlag) {
this.gs2CbindFlag = gs2CbindFlag;
}
public Gs2CbindFlag gs2CbindFlag() {
return gs2CbindFlag;
}
}
private final ChannelBinding channelBinding;
private final StringPreparation stringPreparation;
private final ScramMechanism scramMechanism;
private final SecureRandom secureRandom;
private final NonceSupplier nonceSupplier;
private ScramClient(
ChannelBinding channelBinding, StringPreparation stringPreparation,
ScramMechanism nonChannelBindingMechanism, ScramMechanism channelBindingMechanism,
SecureRandom secureRandom, NonceSupplier nonceSupplier
) {
assert null != channelBinding : "channelBinding";
assert null != stringPreparation : "stringPreparation";
assert null != nonChannelBindingMechanism || null != channelBindingMechanism
: "Either a channel-binding or a non-binding mechanism must be present";
assert null != secureRandom : "secureRandom";
assert null != nonceSupplier : "nonceSupplier";
this.channelBinding = channelBinding;
this.stringPreparation = stringPreparation;
this.scramMechanism = null != nonChannelBindingMechanism ? nonChannelBindingMechanism : channelBindingMechanism;
this.secureRandom = secureRandom;
this.nonceSupplier = nonceSupplier;
}
/**
* Selects for the client whether to use channel binding.
* Refer to {@link ChannelBinding} documentation for the description of the possible values.
* @param channelBinding The channel binding setting
* @return The next step in the chain (PreBuilder1).
* @throws IllegalArgumentException If channelBinding is null
*/
public static PreBuilder1 channelBinding(ChannelBinding channelBinding) throws IllegalArgumentException {
return new PreBuilder1(checkNotNull(channelBinding, "channelBinding"));
}
/**
* This class is not meant to be used directly.
* Use {@link ScramClient#channelBinding(ChannelBinding)} instead.
*/
public static class PreBuilder1 {
protected final ChannelBinding channelBinding;
private PreBuilder1(ChannelBinding channelBinding) {
this.channelBinding = channelBinding;
}
/**
* Selects the string preparation algorithm to use by the client.
* @param stringPreparation The string preparation algorithm
* @throws IllegalArgumentException If stringPreparation is null
*/
public PreBuilder2 stringPreparation(StringPreparation stringPreparation) throws IllegalArgumentException {
return new PreBuilder2(channelBinding, checkNotNull(stringPreparation, "stringPreparation"));
}
}
/**
* This class is not meant to be used directly.
* Use {@link ScramClient#channelBinding(ChannelBinding)}.{#stringPreparation(StringPreparation)} instead.
*/
public static class PreBuilder2 extends PreBuilder1 {
protected final StringPreparation stringPreparation;
protected ScramMechanism nonChannelBindingMechanism = null;
protected ScramMechanism channelBindingMechanism = null;
private PreBuilder2(ChannelBinding channelBinding, StringPreparation stringPreparation) {
super(channelBinding);
this.stringPreparation = stringPreparation;
}
/**
* Inform the client of the SCRAM mechanisms supported by the server.
* Based on this list, the channel binding settings previously specified,
* and the relative strength of the supported SCRAM mechanisms for this client,
* the client will have enough data to select which mechanism to use for future interactions with the server.
* All names provided here need to be standar IANA Registry names for SCRAM mechanisms, or will be ignored.
*
* @see
* SASL SCRAM Family Mechanisms
*
* @param serverMechanisms One or more IANA-registered SCRAM mechanism names, as advertised by the server
* @throws IllegalArgumentException If no server mechanisms are provided
*/
public Builder selectMechanismBasedOnServerAdvertised(String... serverMechanisms) {
checkArgument(null != serverMechanisms && serverMechanisms.length > 0, "serverMechanisms");
nonChannelBindingMechanism = ScramMechanisms.selectMatchingMechanism(false, serverMechanisms);
if(channelBinding == ChannelBinding.NO && null == nonChannelBindingMechanism) {
throw new IllegalArgumentException("Server does not support non channel binding mechanisms");
}
channelBindingMechanism = ScramMechanisms.selectMatchingMechanism(true, serverMechanisms);
if(channelBinding == ChannelBinding.YES && null == channelBindingMechanism) {
throw new IllegalArgumentException("Server does not support channel binding mechanisms");
}
if(null == channelBindingMechanism && null == nonChannelBindingMechanism) {
throw new IllegalArgumentException("There are no matching mechanisms between client and server");
}
return new Builder(channelBinding, stringPreparation, nonChannelBindingMechanism, channelBindingMechanism);
}
/**
* Inform the client of the SCRAM mechanisms supported by the server.
* Calls {@link Builder#selectMechanismBasedOnServerAdvertised(String...)}
* with the results of splitting the received comma-separated values.
* @param serverMechanismsCsv A CSV (Comma-Separated Values) String, containining all the SCRAM mechanisms
* supported by the server
* @throws IllegalArgumentException If selectMechanismBasedOnServerAdvertisedCsv is null
*/
public Builder selectMechanismBasedOnServerAdvertisedCsv(String serverMechanismsCsv)
throws IllegalArgumentException {
return selectMechanismBasedOnServerAdvertised(
checkNotNull(serverMechanismsCsv, "serverMechanismsCsv").split(",")
);
}
/**
* Select a fixed client mechanism. It must be compatible with the channel binding selection previously
* performed. If automatic selection based on server advertised mechanisms is preferred, please use methods
* {@link Builder#selectMechanismBasedOnServerAdvertised(String...)} or
* {@link Builder#selectMechanismBasedOnServerAdvertisedCsv(String)}.
* @param scramMechanism The selected scram mechanism
* @throws IllegalArgumentException If the selected mechanism is null or not compatible with the prior
* channel binding selection,
* or channel binding selection is dependent on the server advertised methods
*/
public Builder selectClientMechanism(ScramMechanism scramMechanism) {
checkNotNull(scramMechanism, "scramMechanism");
if(channelBinding == ChannelBinding.IF_SERVER_SUPPORTS_IT) {
throw new IllegalArgumentException(
"If server selection is considered, no direct client selection should be performed"
);
}
if(
channelBinding == ChannelBinding.YES && ! scramMechanism.supportsChannelBinding()
||
channelBinding == ChannelBinding.NO && scramMechanism.supportsChannelBinding()
) {
throw new IllegalArgumentException("Incompatible selection of mechanism and channel binding");
}
if(scramMechanism.supportsChannelBinding()) {
return new Builder(channelBinding, stringPreparation, null, scramMechanism);
} else {
return new Builder(channelBinding, stringPreparation, scramMechanism, null);
}
}
}
/**
* This class is not meant to be used directly.
* Use instead {@link ScramClient#channelBinding(ChannelBinding)} and chained methods.
*/
public static class Builder extends PreBuilder2 {
private final ScramMechanism nonChannelBindingMechanism;
private final ScramMechanism channelBindingMechanism;
private SecureRandom secureRandom = new SecureRandom();
private NonceSupplier nonceSupplier;
private int nonceLength = DEFAULT_NONCE_LENGTH;
private Builder(
ChannelBinding channelBinding, StringPreparation stringPreparation,
ScramMechanism nonChannelBindingMechanism, ScramMechanism channelBindingMechanism
) {
super(channelBinding, stringPreparation);
this.nonChannelBindingMechanism = nonChannelBindingMechanism;
this.channelBindingMechanism = channelBindingMechanism;
}
/**
* Optional call. Selects a non-default SecureRandom instance,
* based on the given algorithm and optionally provider.
* This SecureRandom instance will be used to generate secure random values,
* like the ones required to generate the nonce
* (unless an external nonce provider is given via {@link Builder#nonceSupplier(NonceSupplier)}).
* Algorithm and provider names are those supported by the {@link SecureRandom} class.
* @param algorithm The name of the algorithm to use.
* @param provider The name of the provider of SecureRandom. Might be null.
* @return The same class
* @throws IllegalArgumentException If algorithm is null, or either the algorithm or provider are not supported
*/
public Builder secureRandomAlgorithmProvider(String algorithm, String provider)
throws IllegalArgumentException {
checkNotNull(algorithm, "algorithm");
try {
secureRandom = null == provider ?
SecureRandom.getInstance(algorithm) :
SecureRandom.getInstance(algorithm, provider);
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new IllegalArgumentException("Invalid algorithm or provider", e);
}
return this;
}
/**
* Optional call. The client will use a default nonce generator,
* unless an external one is provided by this method. *
* @param nonceSupplier A supplier of valid nonce Strings.
* Please note that according to the
* SCRAM RFC
* only ASCII printable characters (except the comma, ',') are permitted on a nonce.
* Length is not limited.
* @return The same class
* @throws IllegalArgumentException If nonceSupplier is null
*/
public Builder nonceSupplier(NonceSupplier nonceSupplier) throws IllegalArgumentException {
this.nonceSupplier = checkNotNull(nonceSupplier, "nonceSupplier");
return this;
}
/**
* Sets a non-default ({@link ScramClient#DEFAULT_NONCE_LENGTH}) length for the nonce generation,
* if no alternate nonceSupplier is provided via {@link Builder#nonceSupplier(NonceSupplier)}.
* @param length The length of the nonce. Must be positive and greater than 0
* @return The same class
* @throws IllegalArgumentException If length is less than 1
*/
public Builder nonceLength(int length) throws IllegalArgumentException {
this.nonceLength = gt0(length, "length");
return this;
}
/**
* Gets the client, fully constructed and configured, with the provided channel binding, string preparation
* properties, and the selected SCRAM mechanism based on server supported mechanisms.
* If no SecureRandom algorithm and provider were provided, a default one would be used.
* If no nonceSupplier was provided, a default nonce generator would be used,
* of the {@link ScramClient#DEFAULT_NONCE_LENGTH} length, unless {@link Builder#nonceLength(int)} is called.
* @return The fully built instance.
*/
public ScramClient setup() {
return new ScramClient(
channelBinding, stringPreparation, nonChannelBindingMechanism, channelBindingMechanism,
secureRandom,
nonceSupplier != null ? nonceSupplier : new NonceSupplier() {
@Override
public String get() {
return CryptoUtil.nonce(nonceLength, secureRandom);
}
}
);
}
}
public StringPreparation getStringPreparation() {
return stringPreparation;
}
public ScramMechanism getScramMechanism() {
return scramMechanism;
}
/**
* List all the supported SCRAM mechanisms by this client implementation
* @return A list of the IANA-registered, SCRAM supported mechanisms
*/
public static List supportedMechanisms() {
List supportedMechanisms = new ArrayList<>();
for (ScramMechanisms scramMechanisms : ScramMechanisms.values()) {
supportedMechanisms.add(scramMechanisms.getName());
}
return supportedMechanisms;
}
/**
* Instantiates a {@link ScramSession} for the specified user and this parametrized generator.
* @param user The username of the authentication exchange
* @return The ScramSession instance
*/
public ScramSession scramSession(String user) {
return new ScramSession(scramMechanism, stringPreparation, checkNotEmpty(user, "user"), nonceSupplier.get());
}
}
scram-2.1/client/src/main/java/com/ongres/scram/client/ScramSession.java 0000664 0000000 0000000 00000030776 13535653744 0026341 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.client;
import static com.ongres.scram.common.util.Preconditions.checkNotEmpty;
import static com.ongres.scram.common.util.Preconditions.checkNotNull;
import com.ongres.scram.common.ScramFunctions;
import com.ongres.scram.common.ScramMechanism;
import com.ongres.scram.common.bouncycastle.base64.Base64;
import com.ongres.scram.common.exception.ScramInvalidServerSignatureException;
import com.ongres.scram.common.exception.ScramParseException;
import com.ongres.scram.common.exception.ScramServerErrorException;
import com.ongres.scram.common.gssapi.Gs2CbindFlag;
import com.ongres.scram.common.message.ClientFinalMessage;
import com.ongres.scram.common.message.ClientFirstMessage;
import com.ongres.scram.common.message.ServerFinalMessage;
import com.ongres.scram.common.message.ServerFirstMessage;
import com.ongres.scram.common.stringprep.StringPreparation;
/**
* A class that represents a SCRAM client. Use this class to perform a SCRAM negotiation with a SCRAM server.
* This class performs an authentication execution for a given user, and has state related to it.
* Thus, it cannot be shared across users or authentication executions.
*/
public class ScramSession {
private final ScramMechanism scramMechanism;
private final StringPreparation stringPreparation;
private final String user;
private final String nonce;
private ClientFirstMessage clientFirstMessage;
private String serverFirstMessageString;
/**
* Constructs a SCRAM client, to perform an authentication for a given user.
* This class can be instantiated directly,
* but it is recommended that a {@link ScramClient} is used instead.
* @param scramMechanism The SCRAM mechanism that will be using this client
* @param stringPreparation
* @param user
* @param nonce
*/
public ScramSession(ScramMechanism scramMechanism, StringPreparation stringPreparation, String user, String nonce) {
this.scramMechanism = checkNotNull(scramMechanism, "scramMechanism");
this.stringPreparation = checkNotNull(stringPreparation, "stringPreparation");
this.user = checkNotEmpty(user, "user");
this.nonce = checkNotEmpty(nonce, "nonce");
}
private String setAndReturnClientFirstMessage(ClientFirstMessage clientFirstMessage) {
this.clientFirstMessage = clientFirstMessage;
return clientFirstMessage.toString();
}
/**
* Returns the text representation of a SCRAM client-first-message, with the GSS-API header values indicated.
* @param gs2CbindFlag The channel binding flag
* @param cbindName The channel binding algorithm name, if channel binding is supported, or null
* @param authzid The optional
* @return The message
*/
public String clientFirstMessage(Gs2CbindFlag gs2CbindFlag, String cbindName, String authzid) {
return setAndReturnClientFirstMessage(new ClientFirstMessage(gs2CbindFlag, authzid, cbindName, user, nonce));
}
/**
* Returns the text representation of a SCRAM client-first-message, with no channel binding nor authzid.
* @return The message
*/
public String clientFirstMessage() {
return setAndReturnClientFirstMessage(new ClientFirstMessage(user, nonce));
}
/**
* Process a received server-first-message.
* Generate by calling {@link #receiveServerFirstMessage(String)}.
*/
public class ServerFirstProcessor {
private final ServerFirstMessage serverFirstMessage;
private ServerFirstProcessor(String receivedServerFirstMessage) throws ScramParseException {
serverFirstMessageString = receivedServerFirstMessage;
serverFirstMessage = ServerFirstMessage.parseFrom(receivedServerFirstMessage, nonce);
}
public String getSalt() {
return serverFirstMessage.getSalt();
}
public int getIteration() {
return serverFirstMessage.getIteration();
}
/**
* Generates a {@link ClientFinalProcessor}, that allows to generate the client-final-message and also
* receive and parse the server-first-message. It is based on the user's password.
* @param password The user's password
* @return The handler
* @throws IllegalArgumentException If the message is null or empty
*/
public ClientFinalProcessor clientFinalProcessor(String password) throws IllegalArgumentException {
return new ClientFinalProcessor(
serverFirstMessage.getNonce(),
checkNotEmpty(password, "password"),
getSalt(),
getIteration()
);
}
/**
* Generates a {@link ClientFinalProcessor}, that allows to generate the client-final-message and also
* receive and parse the server-first-message. It is based on the clientKey and storedKey,
* which, if available, provide an optimized path versus providing the original user's password.
* @param clientKey The client key, as per the SCRAM algorithm.
* It can be generated with:
* {@link ScramFunctions#clientKey(ScramMechanism, StringPreparation, String, byte[], int)}
* @param storedKey The stored key, as per the SCRAM algorithm.
* It can be generated from the client key with:
* {@link ScramFunctions#storedKey(ScramMechanism, byte[])}
* @return The handler
* @throws IllegalArgumentException If the message is null or empty
*/
public ClientFinalProcessor clientFinalProcessor(byte[] clientKey, byte[] storedKey)
throws IllegalArgumentException {
return new ClientFinalProcessor(
serverFirstMessage.getNonce(),
checkNotNull(clientKey, "clientKey"),
checkNotNull(storedKey, "storedKey")
);
}
}
/**
* Processor that allows to generate the client-final-message,
* as well as process the server-final-message and verify server's signature.
* Generate the processor by calling either {@link ServerFirstProcessor#clientFinalProcessor(String)}
* or {@link ServerFirstProcessor#clientFinalProcessor(byte[], byte[])}.
*/
public class ClientFinalProcessor {
private final String nonce;
private final byte[] clientKey;
private final byte[] storedKey;
private final byte[] serverKey;
private String authMessage;
private ClientFinalProcessor(String nonce, byte[] clientKey, byte[] storedKey, byte[] serverKey) {
assert null != clientKey : "clientKey";
assert null != storedKey : "storedKey";
assert null != serverKey : "serverKey";
this.nonce = nonce;
this.clientKey = clientKey;
this.storedKey = storedKey;
this.serverKey = serverKey;
}
private ClientFinalProcessor(String nonce, byte[] clientKey, byte[] serverKey) {
this(nonce, clientKey, ScramFunctions.storedKey(scramMechanism, clientKey), serverKey);
}
private ClientFinalProcessor(String nonce, byte[] saltedPassword) {
this(
nonce,
ScramFunctions.clientKey(scramMechanism, saltedPassword),
ScramFunctions.serverKey(scramMechanism, saltedPassword)
);
}
private ClientFinalProcessor(String nonce, String password, String salt, int iteration) {
this(
nonce,
ScramFunctions.saltedPassword(
scramMechanism, stringPreparation, password, Base64.decode(salt), iteration
)
);
}
private synchronized void generateAndCacheAuthMessage(byte[] cbindData) {
if(null != authMessage) {
return;
}
authMessage = clientFirstMessage.writeToWithoutGs2Header(new StringBuffer())
.append(",")
.append(serverFirstMessageString)
.append(",")
.append(ClientFinalMessage.writeToWithoutProof(clientFirstMessage.getGs2Header(), cbindData, nonce))
.toString();
}
/**
* Generates the SCRAM representation of the client-final-message, including the given channel-binding data.
* @param cbindData The bytes of the channel-binding data
* @return The message
* @throws IllegalArgumentException If the channel binding data is null
*/
private String clientFinalMessage(byte[] cbindData) throws IllegalArgumentException {
if(null == authMessage) {
generateAndCacheAuthMessage(cbindData);
}
ClientFinalMessage clientFinalMessage = new ClientFinalMessage(
clientFirstMessage.getGs2Header(),
cbindData,
nonce,
ScramFunctions.clientProof(
clientKey,
ScramFunctions.clientSignature(scramMechanism, storedKey, authMessage)
)
);
return clientFinalMessage.toString();
}
/**
* Generates the SCRAM representation of the client-final-message.
* @return The message
*/
public String clientFinalMessage() {
return clientFinalMessage(null);
}
/**
* Receive and process the server-final-message.
* Server SCRAM signatures is verified.
* @param serverFinalMessage The received server-final-message
* @throws ScramParseException If the message is not a valid server-final-message
* @throws ScramServerErrorException If the server-final-message contained an error
* @throws IllegalArgumentException If the message is null or empty
*/
public void receiveServerFinalMessage(String serverFinalMessage)
throws ScramParseException, ScramServerErrorException, ScramInvalidServerSignatureException,
IllegalArgumentException {
checkNotEmpty(serverFinalMessage, "serverFinalMessage");
ServerFinalMessage message = ServerFinalMessage.parseFrom(serverFinalMessage);
if(message.isError()) {
throw new ScramServerErrorException(message.getError());
}
if(! ScramFunctions.verifyServerSignature(
scramMechanism, serverKey, authMessage, message.getVerifier()
)) {
throw new ScramInvalidServerSignatureException("Invalid server SCRAM signature");
}
}
}
/**
* Constructs a handler for the server-first-message, from its String representation.
* @param serverFirstMessage The message
* @return The handler
* @throws ScramParseException If the message is not a valid server-first-message
* @throws IllegalArgumentException If the message is null or empty
*/
public ServerFirstProcessor receiveServerFirstMessage(String serverFirstMessage)
throws ScramParseException, IllegalArgumentException {
return new ServerFirstProcessor(checkNotEmpty(serverFirstMessage, "serverFirstMessage"));
}
}
scram-2.1/client/src/test/ 0000775 0000000 0000000 00000000000 13535653744 0015524 5 ustar 00root root 0000000 0000000 scram-2.1/client/src/test/java/ 0000775 0000000 0000000 00000000000 13535653744 0016445 5 ustar 00root root 0000000 0000000 scram-2.1/client/src/test/java/com/ 0000775 0000000 0000000 00000000000 13535653744 0017223 5 ustar 00root root 0000000 0000000 scram-2.1/client/src/test/java/com/ongres/ 0000775 0000000 0000000 00000000000 13535653744 0020520 5 ustar 00root root 0000000 0000000 scram-2.1/client/src/test/java/com/ongres/scram/ 0000775 0000000 0000000 00000000000 13535653744 0021625 5 ustar 00root root 0000000 0000000 scram-2.1/client/src/test/java/com/ongres/scram/client/ 0000775 0000000 0000000 00000000000 13535653744 0023103 5 ustar 00root root 0000000 0000000 scram-2.1/client/src/test/java/com/ongres/scram/client/ScramClientTest.java 0000664 0000000 0000000 00000021704 13535653744 0027016 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.client;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.Arrays;
import org.junit.Test;
import com.ongres.scram.common.ScramMechanisms;
import com.ongres.scram.common.stringprep.StringPreparations;
import com.ongres.scram.common.util.CryptoUtil;
public class ScramClientTest {
@Test
public void getValid() {
ScramClient client1 = ScramClient
.channelBinding(ScramClient.ChannelBinding.NO)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertised("SCRAM-SHA-1")
.setup();
ScramClient client2 = ScramClient
.channelBinding(ScramClient.ChannelBinding.YES)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertised("SCRAM-SHA-1", "SCRAM-SHA-256-PLUS")
.nonceLength(64)
.setup();
ScramClient client3 = ScramClient
.channelBinding(ScramClient.ChannelBinding.IF_SERVER_SUPPORTS_IT)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertised("SCRAM-SHA-1", "SCRAM-SHA-1-PLUS")
.nonceSupplier
(new NonceSupplier() {
@Override
public String get() {
return CryptoUtil.nonce(36);
}
})
.setup();
ScramClient client4 = ScramClient
.channelBinding(ScramClient.ChannelBinding.IF_SERVER_SUPPORTS_IT)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertisedCsv("SCRAM-SHA-1,SCRAM-SHA-256-PLUS")
.secureRandomAlgorithmProvider("SHA1PRNG", "SUN")
.nonceLength(64)
.setup();
ScramClient client5 = ScramClient
.channelBinding(ScramClient.ChannelBinding.IF_SERVER_SUPPORTS_IT)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertisedCsv("SCRAM-SHA-1,SCRAM-SHA-256-PLUS")
.secureRandomAlgorithmProvider("SHA1PRNG", null)
.nonceLength(64)
.setup();
ScramClient client6 = ScramClient
.channelBinding(ScramClient.ChannelBinding.NO)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectClientMechanism(ScramMechanisms.SCRAM_SHA_1)
.setup();
ScramClient client7 = ScramClient
.channelBinding(ScramClient.ChannelBinding.YES)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectClientMechanism(ScramMechanisms.SCRAM_SHA_256_PLUS)
.setup();
for (ScramClient client : new ScramClient[] {
client1, client2, client3, client4, client5, client6, client7
}) {
assertNotNull(client);
}
}
@Test
public void getInvalid() {
int n = 0;
try {
assertNotNull(ScramClient
.channelBinding(ScramClient.ChannelBinding.NO)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertised("SCRAM-SHA-1-PLUS")
.setup()
);
} catch (IllegalArgumentException e) { n++; }
try {
assertNotNull(ScramClient
.channelBinding(ScramClient.ChannelBinding.YES)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertised("SCRAM-SHA-1-PLUS,SCRAM-SAH-256-PLUS")
.setup()
);
} catch (IllegalArgumentException e) { n++; }
try {
assertNotNull(ScramClient
.channelBinding(ScramClient.ChannelBinding.IF_SERVER_SUPPORTS_IT)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertised("INVALID-SCRAM-MECHANISM")
.setup()
);
} catch (IllegalArgumentException e) { n++; }
try {
assertNotNull(ScramClient
.channelBinding(ScramClient.ChannelBinding.IF_SERVER_SUPPORTS_IT)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertised("SCRAM-SHA-1", "SCRAM-SHA-1-PLUS")
.nonceSupplier(null)
.setup()
);
} catch (IllegalArgumentException e) { n++; }
try {
assertNotNull(ScramClient
.channelBinding(ScramClient.ChannelBinding.IF_SERVER_SUPPORTS_IT)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertised("SCRAM-SHA-1", "SCRAM-SHA-1-PLUS")
.nonceLength(0)
.setup()
);
} catch (IllegalArgumentException e) { n++; }
try {
assertNotNull(ScramClient
.channelBinding(ScramClient.ChannelBinding.IF_SERVER_SUPPORTS_IT)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertised("SCRAM-SHA-1", "SCRAM-SHA-1-PLUS")
.secureRandomAlgorithmProvider("Invalid algorithm", null)
.setup()
);
} catch (IllegalArgumentException e) { n++; }
try {
assertNotNull(ScramClient
.channelBinding(ScramClient.ChannelBinding.IF_SERVER_SUPPORTS_IT)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertised("SCRAM-SHA-1", "SCRAM-SHA-1-PLUS")
.secureRandomAlgorithmProvider("SHA1PRNG", "Invalid provider")
.setup()
);
} catch (IllegalArgumentException e) { n++; }
try {
assertNotNull(ScramClient
.channelBinding(ScramClient.ChannelBinding.YES)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectClientMechanism(ScramMechanisms.SCRAM_SHA_1)
.setup()
);
} catch (IllegalArgumentException e) { n++; }
try {
assertNotNull(ScramClient
.channelBinding(ScramClient.ChannelBinding.NO)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectClientMechanism(ScramMechanisms.SCRAM_SHA_1_PLUS)
.setup()
);
} catch (IllegalArgumentException e) { n++; }
try {
assertNotNull(ScramClient
.channelBinding(ScramClient.ChannelBinding.IF_SERVER_SUPPORTS_IT)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectClientMechanism(ScramMechanisms.SCRAM_SHA_1)
.setup()
);
} catch (IllegalArgumentException e) { n++; }
assertEquals(10, n);
}
@Test
public void supportedMechanismsTestAll() {
String[] expecteds = new String[] { "SCRAM-SHA-1", "SCRAM-SHA-1-PLUS", "SCRAM-SHA-256", "SCRAM-SHA-256-PLUS" };
Arrays.sort(expecteds);
String[] actuals = ScramClient.supportedMechanisms().toArray(new String[0]);
Arrays.sort(actuals);
assertArrayEquals(
expecteds,
actuals
);
}
}
scram-2.1/client/src/test/java/com/ongres/scram/client/ScramSessionTest.java 0000664 0000000 0000000 00000006065 13535653744 0027226 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.client;
import com.ongres.scram.common.exception.ScramInvalidServerSignatureException;
import com.ongres.scram.common.exception.ScramParseException;
import com.ongres.scram.common.exception.ScramServerErrorException;
import com.ongres.scram.common.stringprep.StringPreparations;
import org.junit.Test;
import static com.ongres.scram.common.RfcExampleSha1.*;
import static org.junit.Assert.*;
public class ScramSessionTest {
private final ScramClient scramClient = ScramClient
.channelBinding(ScramClient.ChannelBinding.NO)
.stringPreparation(StringPreparations.NO_PREPARATION)
.selectMechanismBasedOnServerAdvertised("SCRAM-SHA-1")
.nonceSupplier
(new NonceSupplier() {
@Override
public String get() {
return CLIENT_NONCE;
}
})
.setup();
@Test
public void completeTest()
throws ScramParseException, ScramInvalidServerSignatureException, ScramServerErrorException {
ScramSession scramSession = scramClient.scramSession(USER);
assertEquals(CLIENT_FIRST_MESSAGE, scramSession.clientFirstMessage());
ScramSession.ServerFirstProcessor serverFirstProcessor = scramSession.receiveServerFirstMessage(
SERVER_FIRST_MESSAGE
);
assertEquals(SERVER_SALT, serverFirstProcessor.getSalt());
assertEquals(SERVER_ITERATIONS, serverFirstProcessor.getIteration());
ScramSession.ClientFinalProcessor clientFinalProcessor = serverFirstProcessor.clientFinalProcessor(PASSWORD);
assertEquals(CLIENT_FINAL_MESSAGE, clientFinalProcessor.clientFinalMessage());
clientFinalProcessor.receiveServerFinalMessage(SERVER_FINAL_MESSAGE);
}
}
scram-2.1/common/ 0000775 0000000 0000000 00000000000 13535653744 0013770 5 ustar 00root root 0000000 0000000 scram-2.1/common/pom.xml 0000664 0000000 0000000 00000002571 13535653744 0015312 0 ustar 00root root 0000000 0000000
4.0.0parentcom.ongres.scram2.1commonSCRAM - commonjunitjunittestcom.ongres.stringprepsaslprep1.1org.apache.maven.pluginsmaven-jar-plugin2.6test-jar
scram-2.1/common/spotbugs-exclude.xml 0000664 0000000 0000000 00000000215 13535653744 0020005 0 ustar 00root root 0000000 0000000
scram-2.1/common/src/ 0000775 0000000 0000000 00000000000 13535653744 0014557 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/ 0000775 0000000 0000000 00000000000 13535653744 0015503 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/ 0000775 0000000 0000000 00000000000 13535653744 0016424 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ 0000775 0000000 0000000 00000000000 13535653744 0017202 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/ 0000775 0000000 0000000 00000000000 13535653744 0020477 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/ 0000775 0000000 0000000 00000000000 13535653744 0021604 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/ 0000775 0000000 0000000 00000000000 13535653744 0023074 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/ScramAttributeValue.java 0000664 0000000 0000000 00000005115 13535653744 0027667 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common;
import com.ongres.scram.common.exception.ScramParseException;
import com.ongres.scram.common.util.AbstractCharAttributeValue;
import static com.ongres.scram.common.util.Preconditions.checkNotNull;
/**
* Parse and write SCRAM Attribute-Value pairs.
*/
public class ScramAttributeValue extends AbstractCharAttributeValue {
public ScramAttributeValue(ScramAttributes attribute, String value) {
super(attribute, checkNotNull(value, "value"));
}
public static StringBuffer writeTo(StringBuffer sb, ScramAttributes attribute, String value) {
return new ScramAttributeValue(attribute, value).writeTo(sb);
}
/**
* Parses a potential ScramAttributeValue String.
* @param value The string that contains the Attribute-Value pair.
* @return The parsed class
* @throws ScramParseException If the argument is empty or an invalid Attribute-Value
*/
public static ScramAttributeValue parse(String value)
throws ScramParseException {
if(null == value || value.length() < 3 || value.charAt(1) != '=') {
throw new ScramParseException("Invalid ScramAttributeValue '" + value + "'");
}
return new ScramAttributeValue(ScramAttributes.byChar(value.charAt(0)), value.substring(2));
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/ScramAttributes.java 0000664 0000000 0000000 00000014675 13535653744 0027070 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common;
import com.ongres.scram.common.exception.ScramParseException;
import com.ongres.scram.common.util.CharAttribute;
import java.util.HashMap;
import java.util.Map;
import static com.ongres.scram.common.util.Preconditions.checkNotNull;
/**
* SCRAM Attributes as defined in Section 5.1 of the RFC.
*
* Not all the available attributes may be available in this implementation.
*/
public enum ScramAttributes implements CharAttribute {
/**
* This attribute specifies the name of the user whose password is used for authentication
* (a.k.a. "authentication identity" [RFC4422]).
* If the "a" attribute is not specified (which would normally be the case), this username is also the identity
* that will be associated with the connection subsequent to authentication and authorization.
*
* The client SHOULD prepare the username using the "SASLprep" profile
* [RFC4013] of the "stringprep" algorithm
* [RFC3454] treating it as a query string
* (i.e., unassigned Unicode code points are allowed).
*
* The characters ',' or '=' in usernames are sent as '=2C' and '=3D' respectively.
*/
USERNAME('n'),
/**
* This is an optional attribute, and is part of the GS2 [RFC5801]
* bridge between the GSS-API and SASL. This attribute specifies an authorization identity.
* A client may include it in its first message to the server if it wants to authenticate as one user,
* but subsequently act as a different user. This is typically used by an administrator to perform some management
* task on behalf of another user, or by a proxy in some situations.
*
* If this attribute is omitted (as it normally would be), the authorization identity is assumed to be derived
* from the username specified with the (required) "n" attribute.
*
* The server always authenticates the user specified by the "n" attribute.
* If the "a" attribute specifies a different user, the server associates that identity with the connection after
* successful authentication and authorization checks.
*
* The syntax of this field is the same as that of the "n" field with respect to quoting of '=' and ','.
*/
AUTHZID('a'),
/**
* This attribute specifies a sequence of random printable ASCII characters excluding ','
* (which forms the nonce used as input to the hash function). No quoting is applied to this string.
*/
NONCE('r'),
/**
* This REQUIRED attribute specifies the base64-encoded GS2 header and channel binding data.
* The attribute data consist of:
*
*
* the GS2 header from the client's first message
* (recall that the GS2 header contains a channel binding flag and an optional authzid).
* This header is going to include channel binding type prefix
* (see [RFC5056]),
* if and only if the client is using channel binding;
*
*
* followed by the external channel's channel binding data,
* if and only if the client is using channel binding.
*
*
*/
CHANNEL_BINDING('c'),
/**
* This attribute specifies the base64-encoded salt used by the server for this user.
*/
SALT('s'),
/**
* This attribute specifies an iteration count for the selected hash function and user.
*/
ITERATION('i'),
/**
* This attribute specifies a base64-encoded ClientProof.
*/
CLIENT_PROOF('p'),
/**
* This attribute specifies a base64-encoded ServerSignature.
*/
SERVER_SIGNATURE('v'),
/**
* This attribute specifies an error that occurred during authentication exchange.
* Can help diagnose the reason for the authentication exchange failure.
*/
ERROR('e')
;
private final char attributeChar;
ScramAttributes(char attributeChar) {
this.attributeChar = checkNotNull(attributeChar, "attributeChar");
}
@Override
public char getChar() {
return attributeChar;
}
private static final Map REVERSE_MAPPING = new HashMap();
static {
for(ScramAttributes scramAttribute : values()) {
REVERSE_MAPPING.put(scramAttribute.getChar(), scramAttribute);
}
}
/**
* Find a SCRAMAttribute by its character.
* @param c The character.
* @return The SCRAMAttribute that has that character.
* @throws ScramParseException If no SCRAMAttribute has this character.
*/
public static ScramAttributes byChar(char c) throws ScramParseException {
if(! REVERSE_MAPPING.containsKey(c)) {
throw new ScramParseException("Attribute with char '" + c + "' does not exist");
}
return REVERSE_MAPPING.get(c);
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/ScramFunctions.java 0000664 0000000 0000000 00000022227 13535653744 0026702 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common;
import com.ongres.scram.common.stringprep.StringPreparation;
import com.ongres.scram.common.util.CryptoUtil;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
/**
* Utility functions (e.g. crypto) for SCRAM.
*/
public class ScramFunctions {
private static final byte[] CLIENT_KEY_HMAC_KEY = "Client Key".getBytes(StandardCharsets.UTF_8);
private static final byte[] SERVER_KEY_HMAC_KEY = "Server Key".getBytes(StandardCharsets.UTF_8);
/**
* Compute the salted password, based on the given SCRAM mechanism, the String preparation algorithm,
* the provided salt and the number of iterations.
*
* {@code
* SaltedPassword := Hi(Normalize(password), salt, i)
* }
*
* @param scramMechanism The SCRAM mechanism
* @param stringPreparation The String preparation
* @param password The non-salted password
* @param salt The bytes representing the salt
* @param iteration The number of iterations
* @return The salted password
*/
public static byte[] saltedPassword(
ScramMechanism scramMechanism, StringPreparation stringPreparation, String password, byte[] salt,
int iteration
) {
return scramMechanism.saltedPassword(stringPreparation, password, salt, iteration);
}
/**
* Computes the HMAC of the message and key, using the given SCRAM mechanism.
* @param scramMechanism The SCRAM mechanism
* @param message The message to compute the HMAC
* @param key The key used to initialize the MAC
* @return The computed HMAC
*/
public static byte[] hmac(ScramMechanism scramMechanism, byte[] message, byte[] key) {
return scramMechanism.hmac(key, message);
}
/**
* Generates a client key, from the salted password.
*
* {@code
* ClientKey := HMAC(SaltedPassword, "Client Key")
* }
*
* @param scramMechanism The SCRAM mechanism
* @param saltedPassword The salted password
* @return The client key
*/
public static byte[] clientKey(ScramMechanism scramMechanism, byte[] saltedPassword) {
return hmac(scramMechanism, CLIENT_KEY_HMAC_KEY, saltedPassword);
}
/**
* Generates a client key from the password and salt.
*
* {@code
* SaltedPassword := Hi(Normalize(password), salt, i)
* ClientKey := HMAC(SaltedPassword, "Client Key")
* }
*
* @param scramMechanism The SCRAM mechanism
* @param stringPreparation The String preparation
* @param password The non-salted password
* @param salt The bytes representing the salt
* @param iteration The number of iterations
* @return The client key
*/
public static byte[] clientKey(
ScramMechanism scramMechanism, StringPreparation stringPreparation, String password, byte[] salt,
int iteration
) {
return clientKey(scramMechanism, saltedPassword(scramMechanism, stringPreparation, password, salt, iteration));
}
/**
* Generates a server key, from the salted password.
*
* {@code
* ServerKey := HMAC(SaltedPassword, "Server Key")
* }
*
* @param scramMechanism The SCRAM mechanism
* @param saltedPassword The salted password
* @return The server key
*/
public static byte[] serverKey(ScramMechanism scramMechanism, byte[] saltedPassword) {
return hmac(scramMechanism, SERVER_KEY_HMAC_KEY, saltedPassword);
}
/**
* Generates a server key from the password and salt.
*
* {@code
* SaltedPassword := Hi(Normalize(password), salt, i)
* ServerKey := HMAC(SaltedPassword, "Server Key")
* }
*
* @param scramMechanism The SCRAM mechanism
* @param stringPreparation The String preparation
* @param password The non-salted password
* @param salt The bytes representing the salt
* @param iteration The number of iterations
* @return The server key
*/
public static byte[] serverKey(
ScramMechanism scramMechanism, StringPreparation stringPreparation, String password, byte[] salt,
int iteration
) {
return serverKey(scramMechanism, saltedPassword(scramMechanism, stringPreparation, password, salt, iteration));
}
/**
* Computes the hash function of a given value, based on the SCRAM mechanism hash function.
* @param scramMechanism The SCRAM mechanism
* @param value The value to hash
* @return The hashed value
*/
public static byte[] hash(ScramMechanism scramMechanism, byte[] value) {
return scramMechanism.digest(value);
}
/**
* Generates a stored key, from the salted password.
*
* {@code
* StoredKey := H(ClientKey)
* }
*
* @param scramMechanism The SCRAM mechanism
* @param clientKey The client key
* @return The stored key
*/
public static byte[] storedKey(ScramMechanism scramMechanism, byte[] clientKey) {
return hash(scramMechanism, clientKey);
}
/**
* Computes the SCRAM client signature.
*
* {@code
* ClientSignature := HMAC(StoredKey, AuthMessage)
* }
*
* @param scramMechanism The SCRAM mechanism
* @param storedKey The stored key
* @param authMessage The auth message
* @return The client signature
*/
public static byte[] clientSignature(ScramMechanism scramMechanism, byte[] storedKey, String authMessage) {
return hmac(scramMechanism, authMessage.getBytes(StandardCharsets.UTF_8), storedKey);
}
/**
* Computes the SCRAM client proof to be sent to the server on the client-final-message.
*
* {@code
* ClientProof := ClientKey XOR ClientSignature
* }
*
* @param clientKey The client key
* @param clientSignature The client signature
* @return The client proof
*/
public static byte[] clientProof(byte[] clientKey, byte[] clientSignature) {
return CryptoUtil.xor(clientKey, clientSignature);
}
/**
* Compute the SCRAM server signature.
*
* {@code
* ServerSignature := HMAC(ServerKey, AuthMessage)
* }
*
* @param scramMechanism The SCRAM mechanism
* @param serverKey The server key
* @param authMessage The auth message
* @return The server signature
*/
public static byte[] serverSignature(ScramMechanism scramMechanism, byte[] serverKey, String authMessage) {
return clientSignature(scramMechanism, serverKey, authMessage);
}
/**
* Verifies that a provided client proof is correct.
* @param scramMechanism The SCRAM mechanism
* @param clientProof The provided client proof
* @param storedKey The stored key
* @param authMessage The auth message
* @return True if the client proof is correct
*/
public static boolean verifyClientProof(
ScramMechanism scramMechanism, byte[] clientProof, byte[] storedKey, String authMessage
) {
byte[] clientSignature = clientSignature(scramMechanism, storedKey, authMessage);
byte[] clientKey = CryptoUtil.xor(clientSignature, clientProof);
byte[] computedStoredKey = hash(scramMechanism, clientKey);
return Arrays.equals(storedKey, computedStoredKey);
}
/**
* Verifies that a provided server proof is correct.
* @param scramMechanism The SCRAM mechanism
* @param serverKey The server key
* @param authMessage The auth message
* @param serverSignature The provided server signature
* @return True if the server signature is correct
*/
public static boolean verifyServerSignature(
ScramMechanism scramMechanism, byte[] serverKey, String authMessage, byte[] serverSignature
) {
return Arrays.equals(serverSignature(scramMechanism, serverKey, authMessage), serverSignature);
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/ScramMechanism.java 0000664 0000000 0000000 00000006415 13535653744 0026637 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common;
import com.ongres.scram.common.stringprep.StringPreparation;
/**
* Definition of the functionality to be provided by every ScramMechanism.
*
* Every ScramMechanism implemented must provide implementations of their respective digest and hmac
* function that will not throw a RuntimeException on any JVM, to guarantee true portability of this library.
*/
public interface ScramMechanism {
/**
* The name of the mechanism, which must be a value registered under IANA:
*
* SASL SCRAM Family Mechanisms
* @return The mechanism name
*/
String getName();
/**
* Calculate a message digest, according to the algorithm of the SCRAM mechanism.
* @param message the message
* @return The calculated message digest
* @throws RuntimeException If the algorithm is not provided by current JVM or any included implementations
*/
byte[] digest(byte[] message) throws RuntimeException;
/**
* Calculate the hmac of a key and a message, according to the algorithm of the SCRAM mechanism.
* @param key the key
* @param message the message
* @return The calculated message hmac instance
* @throws RuntimeException If the algorithm is not provided by current JVM or any included implementations
*/
byte[] hmac(byte[] key, byte[] message) throws RuntimeException;
/**
* Returns the length of the key length of the algorithm.
* @return The length (in bits)
*/
int algorithmKeyLength();
/**
* Whether this mechanism supports channel binding
* @return True if it supports channel binding, false otherwise
*/
boolean supportsChannelBinding();
/**
* Compute the salted password
* @return The salted password
*/
byte[] saltedPassword(StringPreparation stringPreparation, String password,
byte[] salt, int iteration);
}
scram-2.1/common/src/main/java/com/ongres/scram/common/ScramMechanisms.java 0000664 0000000 0000000 00000022770 13535653744 0027024 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common;
import static com.ongres.scram.common.util.Preconditions.checkNotNull;
import static com.ongres.scram.common.util.Preconditions.gt0;
import com.ongres.scram.common.bouncycastle.pbkdf2.DigestFactory;
import com.ongres.scram.common.bouncycastle.pbkdf2.KeyParameter;
import com.ongres.scram.common.bouncycastle.pbkdf2.PBEParametersGenerator;
import com.ongres.scram.common.bouncycastle.pbkdf2.PKCS5S2ParametersGenerator;
import com.ongres.scram.common.stringprep.StringPreparation;
import com.ongres.scram.common.util.CryptoUtil;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Mac;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.SecretKeySpec;
/**
* SCRAM Mechanisms supported by this library.
* At least, SCRAM-SHA-1 and SCRAM-SHA-256 are provided, since both the hash and the HMAC implementations
* are provided by the Java JDK version 6 or greater.
*
* {@link java.security.MessageDigest}: "Every implementation of the Java platform is required to support the
* following standard MessageDigest algorithms: MD5, SHA-1, SHA-256".
*
* {@link javax.crypto.Mac}: "Every implementation of the Java platform is required to support the following
* standard Mac algorithms: HmacMD5, HmacSHA1, HmacSHA256".
*
* @see
* SASL SCRAM Family Mechanisms
*/
public enum ScramMechanisms implements ScramMechanism {
SCRAM_SHA_1 ( "SHA-1", "SHA-1", 160, "HmacSHA1", false, 1 ),
SCRAM_SHA_1_PLUS ( "SHA-1", "SHA-1", 160, "HmacSHA1", true, 1 ),
SCRAM_SHA_256 ( "SHA-256", "SHA-256", 256, "HmacSHA256", false, 10 ),
SCRAM_SHA_256_PLUS ( "SHA-256", "SHA-256", 256, "HmacSHA256", true, 10 )
;
private static final String SCRAM_MECHANISM_NAME_PREFIX = "SCRAM-";
private static final String CHANNEL_BINDING_SUFFIX = "-PLUS";
private static final String PBKDF2_PREFIX_ALGORITHM_NAME = "PBKDF2With";
private static final Map BY_NAME_MAPPING = valuesAsMap();
private final String mechanismName;
private final String hashAlgorithmName;
private final int keyLength;
private final String hmacAlgorithmName;
private final boolean channelBinding;
private final int priority;
ScramMechanisms(
String name, String hashAlgorithmName, int keyLength, String hmacAlgorithmName, boolean channelBinding,
int priority
) {
this.mechanismName = SCRAM_MECHANISM_NAME_PREFIX
+ checkNotNull(name, "name")
+ (channelBinding ? CHANNEL_BINDING_SUFFIX : "")
;
this.hashAlgorithmName = checkNotNull(hashAlgorithmName, "hashAlgorithmName");
this.keyLength = gt0(keyLength, "keyLength");
this.hmacAlgorithmName = checkNotNull(hmacAlgorithmName, "hmacAlgorithmName");
this.channelBinding = channelBinding;
this.priority = gt0(priority, "priority");
}
/**
* Method that returns the name of the hash algorithm.
* It is protected since should be of no interest for direct users.
* The instance is supposed to provide abstractions over the algorithm names,
* and are not meant to be directly exposed.
* @return The name of the hash algorithm
*/
protected String getHashAlgorithmName() {
return hashAlgorithmName;
}
/**
* Method that returns the name of the HMAC algorithm.
* It is protected since should be of no interest for direct users.
* The instance is supposed to provide abstractions over the algorithm names,
* and are not meant to be directly exposed.
* @return The name of the HMAC algorithm
*/
protected String getHmacAlgorithmName() {
return hmacAlgorithmName;
}
@Override
public String getName() {
return mechanismName;
}
@Override
public boolean supportsChannelBinding() {
return channelBinding;
}
@Override
public int algorithmKeyLength() {
return keyLength;
}
@Override
public byte[] digest(byte[] message) {
try {
return MessageDigest.getInstance(hashAlgorithmName).digest(message);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Algorithm " + hashAlgorithmName + " not present in current JVM");
}
}
@Override
public byte[] hmac(byte[] key, byte[] message) {
try {
return CryptoUtil.hmac(new SecretKeySpec(key, hmacAlgorithmName), Mac.getInstance(hmacAlgorithmName), message);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("MAC Algorithm " + hmacAlgorithmName + " not present in current JVM");
}
}
@Override
public byte[] saltedPassword(StringPreparation stringPreparation, String password, byte[] salt,
int iterations) {
char[] normalizedString = stringPreparation.normalize(password).toCharArray();
try {
return CryptoUtil.hi(
SecretKeyFactory.getInstance(PBKDF2_PREFIX_ALGORITHM_NAME + hmacAlgorithmName),
algorithmKeyLength(),
normalizedString,
salt,
iterations);
} catch (NoSuchAlgorithmException e) {
if(!ScramMechanisms.SCRAM_SHA_256.getHmacAlgorithmName().equals(getHmacAlgorithmName())) {
throw new RuntimeException("Unsupported PBKDF2 for " + mechanismName);
}
PBEParametersGenerator generator = new PKCS5S2ParametersGenerator(DigestFactory.createSHA256());
generator.init(PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(normalizedString), salt, iterations);
KeyParameter params = (KeyParameter)generator.generateDerivedParameters(algorithmKeyLength());
return params.getKey();
}
}
/**
* Gets a SCRAM mechanism, given its standard IANA name.
* @param name The standard IANA full name of the mechanism.
* @return An Optional instance that contains the ScramMechanism if it was found, or empty otherwise.
*/
public static ScramMechanisms byName(String name) {
checkNotNull(name, "name");
return BY_NAME_MAPPING.get(name);
}
/**
* This class classifies SCRAM mechanisms by two properties: whether they support channel binding;
* and a priority, which is higher for safer algorithms (like SHA-256 vs SHA-1).
*
* Given a list of SCRAM mechanisms supported by the peer, pick one that matches the channel binding requirements
* and has the highest priority.
*
* @param channelBinding The type of matching mechanism searched for
* @param peerMechanisms The mechanisms supported by the other peer
* @return The selected mechanism, or null if no mechanism matched
*/
public static ScramMechanism selectMatchingMechanism(boolean channelBinding, String... peerMechanisms) {
ScramMechanisms selectedScramMechanisms = null;
for (String peerMechanism : peerMechanisms) {
ScramMechanisms matchedScramMechanisms = BY_NAME_MAPPING.get(peerMechanism);
if (matchedScramMechanisms != null) {
for (ScramMechanisms candidateScramMechanisms : ScramMechanisms.values()) {
if (channelBinding == candidateScramMechanisms.channelBinding
&& candidateScramMechanisms.mechanismName.equals(matchedScramMechanisms.mechanismName)
&& (selectedScramMechanisms == null
|| selectedScramMechanisms.priority < candidateScramMechanisms.priority)) {
selectedScramMechanisms = candidateScramMechanisms;
}
}
}
}
return selectedScramMechanisms;
}
private static Map valuesAsMap() {
Map mapScramMechanisms = new HashMap<>(values().length);
for (ScramMechanisms scramMechanisms : values()) {
mapScramMechanisms.put(scramMechanisms.getName(), scramMechanisms);
}
return mapScramMechanisms;
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/ScramStringFormatting.java 0000664 0000000 0000000 00000012663 13535653744 0030236 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common;
import static com.ongres.scram.common.util.Preconditions.checkNotEmpty;
import static com.ongres.scram.common.util.Preconditions.checkNotNull;
import java.nio.charset.StandardCharsets;
import com.ongres.scram.common.bouncycastle.base64.Base64;
/**
* Class with static methods that provide support for converting to/from salNames.
* @see [RFC5802] Section 7: Formal Syntax
*/
public class ScramStringFormatting {
/**
* Given a value-safe-char (normalized UTF-8 String),
* return one where characters ',' and '=' are represented by '=2C' or '=3D', respectively.
* @param value The value to convert so saslName
* @return The saslName, with caracter escaped (if any)
*/
public static String toSaslName(String value) {
if(null == value || value.isEmpty()) {
return value;
}
int nComma = 0, nEqual = 0;
char[] originalChars = value.toCharArray();
// Fast path
for(char c : originalChars) {
if(',' == c) { nComma++; }
else if('=' == c) { nEqual++; }
}
if(nComma == 0 && nEqual == 0) {
return value;
}
// Replace chars
char[] saslChars = new char[originalChars.length + nComma * 2 + nEqual * 2];
int i = 0;
for(char c : originalChars) {
if(',' == c) {
saslChars[i++] = '=';
saslChars[i++] = '2';
saslChars[i++] = 'C';
} else if('=' == c) {
saslChars[i++] = '=';
saslChars[i++] = '3';
saslChars[i++] = 'D';
} else {
saslChars[i++] = c;
}
}
return new String(saslChars);
}
/**
* Given a saslName, return a non-escaped String.
* @param value The saslName
* @return The saslName, unescaped
* @throws IllegalArgumentException If a ',' character is present, or a '=' not followed by either '2C' or '3D'
*/
public static String fromSaslName(String value) throws IllegalArgumentException {
if(null == value || value.isEmpty()) {
return value;
}
int nEqual = 0;
char[] orig = value.toCharArray();
// Fast path
for(int i = 0; i < orig.length; i++) {
if(orig[i] == ',') {
throw new IllegalArgumentException("Invalid ',' character present in saslName");
}
if(orig[i] == '=') {
nEqual++;
if(i + 2 > orig.length - 1) {
throw new IllegalArgumentException("Invalid '=' character present in saslName");
}
if(! (orig[i+1] == '2' && orig[i+2] == 'C' || orig[i+1] == '3' && orig[i+2] == 'D')) {
throw new IllegalArgumentException(
"Invalid char '=" + orig[i+1] + orig[i+2] + "' found in saslName"
);
}
}
}
if(nEqual == 0) {
return value;
}
// Replace characters
char[] replaced = new char[orig.length - nEqual * 2];
for(int r = 0, o = 0; r < replaced.length; r++) {
if('=' == orig[o]) {
if(orig[o+1] == '2' && orig[o+2] == 'C') {
replaced[r] = ',';
} else if(orig[o+1] == '3' && orig[o+2] == 'D') {
replaced[r] = '=';
}
o += 3;
} else {
replaced[r] = orig[o];
o += 1;
}
}
return new String(replaced);
}
public static String base64Encode(byte[] value) throws IllegalArgumentException {
return Base64.toBase64String(checkNotNull(value, "value"));
}
public static String base64Encode(String value) throws IllegalArgumentException {
return base64Encode(checkNotEmpty(value, "value").getBytes(StandardCharsets.UTF_8));
}
public static byte[] base64Decode(String value) throws IllegalArgumentException {
return Base64.decode(checkNotEmpty(value, "value"));
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/ 0000775 0000000 0000000 00000000000 13535653744 0025567 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/base64/ 0000775 0000000 0000000 00000000000 13535653744 0026653 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/base64/Base64.java 0000664 0000000 0000000 00000013201 13535653744 0030537 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.base64;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import com.ongres.scram.common.bouncycastle.pbkdf2.Strings;
/**
* Utility class for converting Base64 data to bytes and back again.
*/
public class Base64
{
private static final Encoder encoder = new Base64Encoder();
public static String toBase64String(
byte[] data)
{
return toBase64String(data, 0, data.length);
}
public static String toBase64String(
byte[] data,
int off,
int length)
{
byte[] encoded = encode(data, off, length);
return Strings.fromByteArray(encoded);
}
/**
* encode the input data producing a base 64 encoded byte array.
*
* @return a byte array containing the base 64 encoded data.
*/
public static byte[] encode(
byte[] data)
{
return encode(data, 0, data.length);
}
/**
* encode the input data producing a base 64 encoded byte array.
*
* @return a byte array containing the base 64 encoded data.
*/
public static byte[] encode(
byte[] data,
int off,
int length)
{
int len = (length + 2) / 3 * 4;
ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
try
{
encoder.encode(data, off, length, bOut);
}
catch (Exception e)
{
throw new EncoderException("exception encoding base64 string: " + e.getMessage(), e);
}
return bOut.toByteArray();
}
/**
* Encode the byte data to base 64 writing it to the given output stream.
*
* @return the number of bytes produced.
*/
public static int encode(
byte[] data,
OutputStream out)
throws IOException
{
return encoder.encode(data, 0, data.length, out);
}
/**
* Encode the byte data to base 64 writing it to the given output stream.
*
* @return the number of bytes produced.
*/
public static int encode(
byte[] data,
int off,
int length,
OutputStream out)
throws IOException
{
return encoder.encode(data, off, length, out);
}
/**
* decode the base 64 encoded input data. It is assumed the input data is valid.
*
* @return a byte array representing the decoded data.
*/
public static byte[] decode(
byte[] data)
{
int len = data.length / 4 * 3;
ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
try
{
encoder.decode(data, 0, data.length, bOut);
}
catch (Exception e)
{
throw new DecoderException("unable to decode base64 data: " + e.getMessage(), e);
}
return bOut.toByteArray();
}
/**
* decode the base 64 encoded String data - whitespace will be ignored.
*
* @return a byte array representing the decoded data.
*/
public static byte[] decode(
String data)
{
int len = data.length() / 4 * 3;
ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
try
{
encoder.decode(data, bOut);
}
catch (Exception e)
{
throw new DecoderException("unable to decode base64 string: " + e.getMessage(), e);
}
return bOut.toByteArray();
}
/**
* decode the base 64 encoded String data writing it to the given output stream,
* whitespace characters will be ignored.
*
* @return the number of bytes produced.
*/
public static int decode(
String data,
OutputStream out)
throws IOException
{
return encoder.decode(data, out);
}
/**
* Decode to an output stream;
*
* @param base64Data The source data.
* @param start Start position.
* @param length the length.
* @param out The output stream to write to.
*/
public static int decode(byte[] base64Data, int start, int length, OutputStream out)
{
try
{
return encoder.decode(base64Data, start, length, out);
}
catch (Exception e)
{
throw new DecoderException("unable to decode base64 data: " + e.getMessage(), e);
}
}
} scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/base64/Base64Encoder.java 0000664 0000000 0000000 00000025770 13535653744 0032055 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.base64;
import java.io.IOException;
import java.io.OutputStream;
/**
* A streaming Base64 encoder.
*/
public class Base64Encoder
implements Encoder
{
protected final byte[] encodingTable =
{
(byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
(byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
(byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
(byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
(byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
(byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
(byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
(byte)'v',
(byte)'w', (byte)'x', (byte)'y', (byte)'z',
(byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
(byte)'7', (byte)'8', (byte)'9',
(byte)'+', (byte)'/'
};
protected byte padding = (byte)'=';
/*
* set up the decoding table.
*/
protected final byte[] decodingTable = new byte[128];
protected void initialiseDecodingTable()
{
for (int i = 0; i < decodingTable.length; i++)
{
decodingTable[i] = (byte)0xff;
}
for (int i = 0; i < encodingTable.length; i++)
{
decodingTable[encodingTable[i]] = (byte)i;
}
}
public Base64Encoder()
{
initialiseDecodingTable();
}
/**
* encode the input data producing a base 64 output stream.
*
* @return the number of bytes produced.
*/
public int encode(
byte[] data,
int off,
int length,
OutputStream out)
throws IOException
{
int modulus = length % 3;
int dataLength = (length - modulus);
int a1, a2, a3;
for (int i = off; i < off + dataLength; i += 3)
{
a1 = data[i] & 0xff;
a2 = data[i + 1] & 0xff;
a3 = data[i + 2] & 0xff;
out.write(encodingTable[(a1 >>> 2) & 0x3f]);
out.write(encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f]);
out.write(encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f]);
out.write(encodingTable[a3 & 0x3f]);
}
/*
* process the tail end.
*/
int b1, b2, b3;
int d1, d2;
switch (modulus)
{
case 0: /* nothing left to do */
break;
case 1:
d1 = data[off + dataLength] & 0xff;
b1 = (d1 >>> 2) & 0x3f;
b2 = (d1 << 4) & 0x3f;
out.write(encodingTable[b1]);
out.write(encodingTable[b2]);
out.write(padding);
out.write(padding);
break;
case 2:
d1 = data[off + dataLength] & 0xff;
d2 = data[off + dataLength + 1] & 0xff;
b1 = (d1 >>> 2) & 0x3f;
b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
b3 = (d2 << 2) & 0x3f;
out.write(encodingTable[b1]);
out.write(encodingTable[b2]);
out.write(encodingTable[b3]);
out.write(padding);
break;
}
return (dataLength / 3) * 4 + ((modulus == 0) ? 0 : 4);
}
private boolean ignore(
char c)
{
return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
}
/**
* decode the base 64 encoded byte data writing it to the given output stream,
* whitespace characters will be ignored.
*
* @return the number of bytes produced.
*/
public int decode(
byte[] data,
int off,
int length,
OutputStream out)
throws IOException
{
byte b1, b2, b3, b4;
int outLen = 0;
int end = off + length;
while (end > off)
{
if (!ignore((char)data[end - 1]))
{
break;
}
end--;
}
// empty data!
if (end == 0)
{
return 0;
}
int i = 0;
int finish = end;
while (finish > off && i != 4)
{
if (!ignore((char)data[finish - 1]))
{
i++;
}
finish--;
}
i = nextI(data, off, finish);
while (i < finish)
{
b1 = decodingTable[data[i++]];
i = nextI(data, i, finish);
b2 = decodingTable[data[i++]];
i = nextI(data, i, finish);
b3 = decodingTable[data[i++]];
i = nextI(data, i, finish);
b4 = decodingTable[data[i++]];
if ((b1 | b2 | b3 | b4) < 0)
{
throw new IOException("invalid characters encountered in base64 data");
}
out.write((b1 << 2) | (b2 >> 4));
out.write((b2 << 4) | (b3 >> 2));
out.write((b3 << 6) | b4);
outLen += 3;
i = nextI(data, i, finish);
}
int e0 = nextI(data, i, end);
int e1 = nextI(data, e0 + 1, end);
int e2 = nextI(data, e1 + 1, end);
int e3 = nextI(data, e2 + 1, end);
outLen += decodeLastBlock(out, (char)data[e0], (char)data[e1], (char)data[e2], (char)data[e3]);
return outLen;
}
private int nextI(byte[] data, int i, int finish)
{
while ((i < finish) && ignore((char)data[i]))
{
i++;
}
return i;
}
/**
* decode the base 64 encoded String data writing it to the given output stream,
* whitespace characters will be ignored.
*
* @return the number of bytes produced.
*/
public int decode(
String data,
OutputStream out)
throws IOException
{
byte b1, b2, b3, b4;
int length = 0;
int end = data.length();
while (end > 0)
{
if (!ignore(data.charAt(end - 1)))
{
break;
}
end--;
}
// empty data!
if (end == 0)
{
return 0;
}
int i = 0;
int finish = end;
while (finish > 0 && i != 4)
{
if (!ignore(data.charAt(finish - 1)))
{
i++;
}
finish--;
}
i = nextI(data, 0, finish);
while (i < finish)
{
b1 = decodingTable[data.charAt(i++)];
i = nextI(data, i, finish);
b2 = decodingTable[data.charAt(i++)];
i = nextI(data, i, finish);
b3 = decodingTable[data.charAt(i++)];
i = nextI(data, i, finish);
b4 = decodingTable[data.charAt(i++)];
if ((b1 | b2 | b3 | b4) < 0)
{
throw new IOException("invalid characters encountered in base64 data");
}
out.write((b1 << 2) | (b2 >> 4));
out.write((b2 << 4) | (b3 >> 2));
out.write((b3 << 6) | b4);
length += 3;
i = nextI(data, i, finish);
}
int e0 = nextI(data, i, end);
int e1 = nextI(data, e0 + 1, end);
int e2 = nextI(data, e1 + 1, end);
int e3 = nextI(data, e2 + 1, end);
length += decodeLastBlock(out, data.charAt(e0), data.charAt(e1), data.charAt(e2), data.charAt(e3));
return length;
}
private int decodeLastBlock(OutputStream out, char c1, char c2, char c3, char c4)
throws IOException
{
byte b1, b2, b3, b4;
if (c3 == padding)
{
if (c4 != padding)
{
throw new IOException("invalid characters encountered at end of base64 data");
}
b1 = decodingTable[c1];
b2 = decodingTable[c2];
if ((b1 | b2) < 0)
{
throw new IOException("invalid characters encountered at end of base64 data");
}
out.write((b1 << 2) | (b2 >> 4));
return 1;
}
else if (c4 == padding)
{
b1 = decodingTable[c1];
b2 = decodingTable[c2];
b3 = decodingTable[c3];
if ((b1 | b2 | b3) < 0)
{
throw new IOException("invalid characters encountered at end of base64 data");
}
out.write((b1 << 2) | (b2 >> 4));
out.write((b2 << 4) | (b3 >> 2));
return 2;
}
else
{
b1 = decodingTable[c1];
b2 = decodingTable[c2];
b3 = decodingTable[c3];
b4 = decodingTable[c4];
if ((b1 | b2 | b3 | b4) < 0)
{
throw new IOException("invalid characters encountered at end of base64 data");
}
out.write((b1 << 2) | (b2 >> 4));
out.write((b2 << 4) | (b3 >> 2));
out.write((b3 << 6) | b4);
return 3;
}
}
private int nextI(String data, int i, int finish)
{
while ((i < finish) && ignore(data.charAt(i)))
{
i++;
}
return i;
}
} scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/base64/DecoderException.java 0000664 0000000 0000000 00000003334 13535653744 0032745 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.base64;
/**
* Exception thrown if an attempt is made to decode invalid data, or some other failure occurs.
*/
public class DecoderException
extends IllegalStateException
{
private Throwable cause;
DecoderException(String msg, Throwable cause)
{
super(msg);
this.cause = cause;
}
public Throwable getCause()
{
return cause;
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/base64/Encoder.java 0000664 0000000 0000000 00000003414 13535653744 0031077 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.base64;
import java.io.IOException;
import java.io.OutputStream;
/**
* Encode and decode byte arrays (typically from binary to 7-bit ASCII
* encodings).
*/
public interface Encoder
{
int encode(byte[] data, int off, int length, OutputStream out) throws IOException;
int decode(byte[] data, int off, int length, OutputStream out) throws IOException;
int decode(String data, OutputStream out) throws IOException;
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/base64/EncoderException.java 0000664 0000000 0000000 00000003334 13535653744 0032757 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.base64;
/**
* Exception thrown if an attempt is made to encode invalid data, or some other failure occurs.
*/
public class EncoderException
extends IllegalStateException
{
private Throwable cause;
EncoderException(String msg, Throwable cause)
{
super(msg);
this.cause = cause;
}
public Throwable getCause()
{
return cause;
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/ 0000775 0000000 0000000 00000000000 13535653744 0026737 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/Arrays.java 0000664 0000000 0000000 00000005303 13535653744 0031044 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* General array utilities.
*/
public final class Arrays
{
private Arrays()
{
// static class, hide constructor
}
/**
* Make a copy of a range of bytes from the passed in data array. The range can
* extend beyond the end of the input array, in which case the return array will
* be padded with zeroes.
*
* @param data the array from which the data is to be copied.
* @param from the start index at which the copying should take place.
* @param to the final index of the range (exclusive).
*
* @return a new byte array containing the range given.
*/
public static byte[] copyOfRange(byte[] data, int from, int to)
{
int newLength = getLength(from, to);
byte[] tmp = new byte[newLength];
if (data.length - from < newLength)
{
System.arraycopy(data, from, tmp, 0, data.length - from);
}
else
{
System.arraycopy(data, from, tmp, 0, newLength);
}
return tmp;
}
private static int getLength(int from, int to)
{
int newLength = to - from;
if (newLength < 0)
{
StringBuffer sb = new StringBuffer(from);
sb.append(" > ").append(to);
throw new IllegalArgumentException(sb.toString());
}
return newLength;
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/CipherParameters.java 0000664 0000000 0000000 00000002667 13535653744 0033053 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* all parameter classes implement this.
*/
public interface CipherParameters
{
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/DataLengthException.java 0000664 0000000 0000000 00000003765 13535653744 0033507 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* this exception is thrown if a buffer that is meant to have output
* copied into it turns out to be too short, or if we've been given
* insufficient input. In general this exception will get thrown rather
* than an ArrayOutOfBounds exception.
*/
public class DataLengthException
extends RuntimeCryptoException
{
/**
* base constructor.
*/
public DataLengthException()
{
}
/**
* create a DataLengthException with the given message.
*
* @param message the message to be carried with the exception.
*/
public DataLengthException(
String message)
{
super(message);
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/Digest.java 0000664 0000000 0000000 00000005171 13535653744 0031025 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* interface that a message digest conforms to.
*/
public interface Digest
{
/**
* return the algorithm name
*
* @return the algorithm name
*/
public String getAlgorithmName();
/**
* return the size, in bytes, of the digest produced by this message digest.
*
* @return the size, in bytes, of the digest produced by this message digest.
*/
public int getDigestSize();
/**
* update the message digest with a single byte.
*
* @param in the input byte to be entered.
*/
public void update(byte in);
/**
* update the message digest with a block of bytes.
*
* @param in the byte array containing the data.
* @param inOff the offset into the byte array where the data starts.
* @param len the length of the data.
*/
public void update(byte[] in, int inOff, int len);
/**
* close the digest, producing the final digest value. The doFinal
* call leaves the digest reset.
*
* @param out the array the digest is to be copied into.
* @param outOff the offset into the out array the digest is to start at.
*/
public int doFinal(byte[] out, int outOff);
/**
* reset the digest back to it's initial state.
*/
public void reset();
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/DigestFactory.java 0000664 0000000 0000000 00000003020 13535653744 0032344 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* Basic factory class for message digests.
*/
public final class DigestFactory
{
public static Digest createSHA256()
{
return new SHA256Digest();
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/EncodableDigest.java 0000664 0000000 0000000 00000003677 13535653744 0032633 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* Encodable digests allow you to download an encoded copy of their internal state. This is useful for the situation where
* you need to generate a signature on an external device and it allows for "sign with last round", so a copy of the
* internal state of the digest, plus the last few blocks of the message are all that needs to be sent, rather than the
* entire message.
*/
public interface EncodableDigest
{
/**
* Return an encoded byte array for the digest's internal state
*
* @return an encoding of the digests internal state.
*/
byte[] getEncodedState();
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/ExtendedDigest.java 0000664 0000000 0000000 00000003172 13535653744 0032505 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
public interface ExtendedDigest
extends Digest
{
/**
* Return the size in bytes of the internal buffer the digest applies it's compression
* function to.
*
* @return byte length of the digests internal buffer.
*/
public int getByteLength();
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/GeneralDigest.java 0000664 0000000 0000000 00000010745 13535653744 0032326 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* base implementation of MD4 family style digest as outlined in
* "Handbook of Applied Cryptography", pages 344 - 347.
*/
public abstract class GeneralDigest
implements ExtendedDigest, Memoable
{
private static final int BYTE_LENGTH = 64;
private final byte[] xBuf = new byte[4];
private int xBufOff;
private long byteCount;
/**
* Standard constructor
*/
protected GeneralDigest()
{
xBufOff = 0;
}
/**
* Copy constructor. We are using copy constructors in place
* of the Object.clone() interface as this interface is not
* supported by J2ME.
*/
protected GeneralDigest(GeneralDigest t)
{
copyIn(t);
}
protected GeneralDigest(byte[] encodedState)
{
System.arraycopy(encodedState, 0, xBuf, 0, xBuf.length);
xBufOff = Pack.bigEndianToInt(encodedState, 4);
byteCount = Pack.bigEndianToLong(encodedState, 8);
}
protected void copyIn(GeneralDigest t)
{
System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
xBufOff = t.xBufOff;
byteCount = t.byteCount;
}
public void update(
byte in)
{
xBuf[xBufOff++] = in;
if (xBufOff == xBuf.length)
{
processWord(xBuf, 0);
xBufOff = 0;
}
byteCount++;
}
public void update(
byte[] in,
int inOff,
int len)
{
len = Math.max(0, len);
//
// fill the current word
//
int i = 0;
if (xBufOff != 0)
{
while (i < len)
{
xBuf[xBufOff++] = in[inOff + i++];
if (xBufOff == 4)
{
processWord(xBuf, 0);
xBufOff = 0;
break;
}
}
}
//
// process whole words.
//
int limit = ((len - i) & ~3) + i;
for (; i < limit; i += 4)
{
processWord(in, inOff + i);
}
//
// load in the remainder.
//
while (i < len)
{
xBuf[xBufOff++] = in[inOff + i++];
}
byteCount += len;
}
public void finish()
{
long bitLength = (byteCount << 3);
//
// add the pad bytes.
//
update((byte)128);
while (xBufOff != 0)
{
update((byte)0);
}
processLength(bitLength);
processBlock();
}
public void reset()
{
byteCount = 0;
xBufOff = 0;
for (int i = 0; i < xBuf.length; i++)
{
xBuf[i] = 0;
}
}
protected void populateState(byte[] state)
{
System.arraycopy(xBuf, 0, state, 0, xBufOff);
Pack.intToBigEndian(xBufOff, state, 4);
Pack.longToBigEndian(byteCount, state, 8);
}
public int getByteLength()
{
return BYTE_LENGTH;
}
protected abstract void processWord(byte[] in, int inOff);
protected abstract void processLength(long bitLength);
protected abstract void processBlock();
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/HMac.java 0000664 0000000 0000000 00000014717 13535653744 0030424 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
import java.util.Hashtable;
/**
* HMAC implementation based on RFC2104
*
* H(K XOR opad, H(K XOR ipad, text))
*/
public class HMac
implements Mac
{
private final static byte IPAD = (byte)0x36;
private final static byte OPAD = (byte)0x5C;
private Digest digest;
private int digestSize;
private int blockLength;
private Memoable ipadState;
private Memoable opadState;
private byte[] inputPad;
private byte[] outputBuf;
private static Hashtable blockLengths;
static
{
blockLengths = new Hashtable<>();
blockLengths.put("GOST3411", Integers.valueOf(32));
blockLengths.put("MD2", Integers.valueOf(16));
blockLengths.put("MD4", Integers.valueOf(64));
blockLengths.put("MD5", Integers.valueOf(64));
blockLengths.put("RIPEMD128", Integers.valueOf(64));
blockLengths.put("RIPEMD160", Integers.valueOf(64));
blockLengths.put("SHA-1", Integers.valueOf(64));
blockLengths.put("SHA-224", Integers.valueOf(64));
blockLengths.put("SHA-256", Integers.valueOf(64));
blockLengths.put("SHA-384", Integers.valueOf(128));
blockLengths.put("SHA-512", Integers.valueOf(128));
blockLengths.put("Tiger", Integers.valueOf(64));
blockLengths.put("Whirlpool", Integers.valueOf(64));
}
private static int getByteLength(
Digest digest)
{
if (digest instanceof ExtendedDigest)
{
return ((ExtendedDigest)digest).getByteLength();
}
Integer b = (Integer)blockLengths.get(digest.getAlgorithmName());
if (b == null)
{
throw new IllegalArgumentException("unknown digest passed: " + digest.getAlgorithmName());
}
return b.intValue();
}
/**
* Base constructor for one of the standard digest algorithms that the
* byteLength of the algorithm is know for.
*
* @param digest the digest.
*/
public HMac(
Digest digest)
{
this(digest, getByteLength(digest));
}
private HMac(
Digest digest,
int byteLength)
{
this.digest = digest;
this.digestSize = digest.getDigestSize();
this.blockLength = byteLength;
this.inputPad = new byte[blockLength];
this.outputBuf = new byte[blockLength + digestSize];
}
public String getAlgorithmName()
{
return digest.getAlgorithmName() + "/HMAC";
}
public Digest getUnderlyingDigest()
{
return digest;
}
public void init(
CipherParameters params)
{
digest.reset();
byte[] key = ((KeyParameter)params).getKey();
int keyLength = key.length;
if (keyLength > blockLength)
{
digest.update(key, 0, keyLength);
digest.doFinal(inputPad, 0);
keyLength = digestSize;
}
else
{
System.arraycopy(key, 0, inputPad, 0, keyLength);
}
for (int i = keyLength; i < inputPad.length; i++)
{
inputPad[i] = 0;
}
System.arraycopy(inputPad, 0, outputBuf, 0, blockLength);
xorPad(inputPad, blockLength, IPAD);
xorPad(outputBuf, blockLength, OPAD);
if (digest instanceof Memoable)
{
opadState = ((Memoable)digest).copy();
((Digest)opadState).update(outputBuf, 0, blockLength);
}
digest.update(inputPad, 0, inputPad.length);
if (digest instanceof Memoable)
{
ipadState = ((Memoable)digest).copy();
}
}
public int getMacSize()
{
return digestSize;
}
public void update(
byte in)
{
digest.update(in);
}
public void update(
byte[] in,
int inOff,
int len)
{
digest.update(in, inOff, len);
}
public int doFinal(
byte[] out,
int outOff)
{
digest.doFinal(outputBuf, blockLength);
if (opadState != null)
{
((Memoable)digest).reset(opadState);
digest.update(outputBuf, blockLength, digest.getDigestSize());
}
else
{
digest.update(outputBuf, 0, outputBuf.length);
}
int len = digest.doFinal(out, outOff);
for (int i = blockLength; i < outputBuf.length; i++)
{
outputBuf[i] = 0;
}
if (ipadState != null)
{
((Memoable)digest).reset(ipadState);
}
else
{
digest.update(inputPad, 0, inputPad.length);
}
return len;
}
/**
* Reset the mac generator.
*/
public void reset()
{
/*
* reset the underlying digest.
*/
digest.reset();
/*
* reinitialize the digest.
*/
digest.update(inputPad, 0, inputPad.length);
}
private static void xorPad(byte[] pad, int len, byte n)
{
for (int i = 0; i < len; ++i)
{
pad[i] ^= n;
}
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/Integers.java 0000664 0000000 0000000 00000002777 13535653744 0031377 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* Utility methods for ints.
*/
public class Integers
{
public static Integer valueOf(int value)
{
return Integer.valueOf(value);
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/KeyParameter.java 0000664 0000000 0000000 00000003435 13535653744 0032200 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
public class KeyParameter
implements CipherParameters
{
private byte[] key;
public KeyParameter(
byte[] key)
{
this(key, 0, key.length);
}
public KeyParameter(
byte[] key,
int keyOff,
int keyLen)
{
this.key = new byte[keyLen];
System.arraycopy(key, keyOff, this.key, 0, keyLen);
}
public byte[] getKey()
{
return key;
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/Mac.java 0000664 0000000 0000000 00000007026 13535653744 0030307 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* The base interface for implementations of message authentication codes (MACs).
*/
public interface Mac
{
/**
* Initialise the MAC.
*
* @param params the key and other data required by the MAC.
* @exception IllegalArgumentException if the params argument is
* inappropriate.
*/
public void init(CipherParameters params)
throws IllegalArgumentException;
/**
* Return the name of the algorithm the MAC implements.
*
* @return the name of the algorithm the MAC implements.
*/
public String getAlgorithmName();
/**
* Return the block size for this MAC (in bytes).
*
* @return the block size for this MAC in bytes.
*/
public int getMacSize();
/**
* add a single byte to the mac for processing.
*
* @param in the byte to be processed.
* @exception IllegalStateException if the MAC is not initialised.
*/
public void update(byte in)
throws IllegalStateException;
/**
* @param in the array containing the input.
* @param inOff the index in the array the data begins at.
* @param len the length of the input starting at inOff.
* @exception IllegalStateException if the MAC is not initialised.
* @exception DataLengthException if there isn't enough data in in.
*/
public void update(byte[] in, int inOff, int len)
throws DataLengthException, IllegalStateException;
/**
* Compute the final stage of the MAC writing the output to the out
* parameter.
*
* doFinal leaves the MAC in the same state it was after the last init.
*
* @param out the array the MAC is to be output to.
* @param outOff the offset into the out buffer the output is to start at.
* @exception DataLengthException if there isn't enough space in out.
* @exception IllegalStateException if the MAC is not initialised.
*/
public int doFinal(byte[] out, int outOff)
throws DataLengthException, IllegalStateException;
/**
* Reset the MAC. At the end of resetting the MAC should be in the
* in the same state it was after the last init (if there was one).
*/
public void reset();
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/Memoable.java 0000664 0000000 0000000 00000004444 13535653744 0031331 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* Interface for Memoable objects. Memoable objects allow the taking of a snapshot of their internal state
* via the copy() method and then reseting the object back to that state later using the reset() method.
*/
public interface Memoable
{
/**
* Produce a copy of this object with its configuration and in its current state.
*
* The returned object may be used simply to store the state, or may be used as a similar object
* starting from the copied state.
*/
Memoable copy();
/**
* Restore a copied object state into this object.
*
* Implementations of this method should try to avoid or minimise memory allocation to perform the reset.
*
* @param other an object originally {@link #copy() copied} from an object of the same type as this instance.
* @throws ClassCastException if the provided object is not of the correct type.
*/
void reset(Memoable other);
}
PBEParametersGenerator.java 0000664 0000000 0000000 00000006674 13535653744 0034041 0 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* super class for all Password Based Encryption (PBE) parameter generator classes.
*/
public abstract class PBEParametersGenerator
{
protected byte[] password;
protected byte[] salt;
protected int iterationCount;
/**
* base constructor.
*/
protected PBEParametersGenerator()
{
}
/**
* initialise the PBE generator.
*
* @param password the password converted into bytes (see below).
* @param salt the salt to be mixed with the password.
* @param iterationCount the number of iterations the "mixing" function
* is to be applied for.
*/
public void init(
byte[] password,
byte[] salt,
int iterationCount)
{
this.password = password;
this.salt = salt;
this.iterationCount = iterationCount;
}
/**
* return the password byte array.
*
* @return the password byte array.
*/
public byte[] getPassword()
{
return password;
}
/**
* return the salt byte array.
*
* @return the salt byte array.
*/
public byte[] getSalt()
{
return salt;
}
/**
* return the iteration count.
*
* @return the iteration count.
*/
public int getIterationCount()
{
return iterationCount;
}
/**
* generate derived parameters for a key of length keySize.
*
* @param keySize the length, in bits, of the key required.
* @return a parameters object representing a key.
*/
public abstract CipherParameters generateDerivedParameters(int keySize);
/**
* converts a password to a byte array according to the scheme in
* PKCS5 (UTF-8, no padding)
*
* @param password a character array representing the password.
* @return a byte array representing the password.
*/
public static byte[] PKCS5PasswordToUTF8Bytes(
char[] password)
{
if (password != null)
{
return Strings.toUTF8ByteArray(password);
}
else
{
return new byte[0];
}
}
}
PKCS5S2ParametersGenerator.java 0000664 0000000 0000000 00000007532 13535653744 0034457 0 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 2.
* This generator uses a SHA-1 HMac as the calculation function.
*
* The document this implementation is based on can be found at
*
* RSA's PKCS5 Page
*/
public class PKCS5S2ParametersGenerator
extends PBEParametersGenerator
{
private Mac hMac;
private byte[] state;
public PKCS5S2ParametersGenerator(Digest digest)
{
hMac = new HMac(digest);
state = new byte[hMac.getMacSize()];
}
private void F(
byte[] S,
int c,
byte[] iBuf,
byte[] out,
int outOff)
{
if (c == 0)
{
throw new IllegalArgumentException("iteration count must be at least 1.");
}
if (S != null)
{
hMac.update(S, 0, S.length);
}
hMac.update(iBuf, 0, iBuf.length);
hMac.doFinal(state, 0);
System.arraycopy(state, 0, out, outOff, state.length);
for (int count = 1; count < c; count++)
{
hMac.update(state, 0, state.length);
hMac.doFinal(state, 0);
for (int j = 0; j != state.length; j++)
{
out[outOff + j] ^= state[j];
}
}
}
private byte[] generateDerivedKey(
int dkLen)
{
int hLen = hMac.getMacSize();
int l = (dkLen + hLen - 1) / hLen;
byte[] iBuf = new byte[4];
byte[] outBytes = new byte[l * hLen];
int outPos = 0;
CipherParameters param = new KeyParameter(password);
hMac.init(param);
for (int i = 1; i <= l; i++)
{
// Increment the value in 'iBuf'
int pos = 3;
while (++iBuf[pos] == 0)
{
--pos;
}
F(salt, iterationCount, iBuf, outBytes, outPos);
outPos += hLen;
}
return outBytes;
}
/**
* Generate a key parameter derived from the password, salt, and iteration
* count we are currently initialised with.
*
* @param keySize the size of the key we want (in bits)
* @return a KeyParameter object.
*/
public CipherParameters generateDerivedParameters(
int keySize)
{
keySize = keySize / 8;
byte[] dKey = Arrays.copyOfRange(generateDerivedKey(keySize), 0, keySize);
return new KeyParameter(dKey, 0, keySize);
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/Pack.java 0000664 0000000 0000000 00000005572 13535653744 0030471 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* Utility methods for converting byte arrays into ints and longs, and back again.
*/
public abstract class Pack
{
public static int bigEndianToInt(byte[] bs, int off)
{
int n = bs[ off] << 24;
n |= (bs[++off] & 0xff) << 16;
n |= (bs[++off] & 0xff) << 8;
n |= (bs[++off] & 0xff);
return n;
}
public static long bigEndianToLong(byte[] bs, int off)
{
int hi = bigEndianToInt(bs, off);
int lo = bigEndianToInt(bs, off + 4);
return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
}
public static void longToBigEndian(long n, byte[] bs, int off)
{
intToBigEndian((int)(n >>> 32), bs, off);
intToBigEndian((int)(n & 0xffffffffL), bs, off + 4);
}
public static byte[] longToBigEndian(long[] ns)
{
byte[] bs = new byte[8 * ns.length];
longToBigEndian(ns, bs, 0);
return bs;
}
public static void longToBigEndian(long[] ns, byte[] bs, int off)
{
for (int i = 0; i < ns.length; ++i)
{
longToBigEndian(ns[i], bs, off);
off += 8;
}
}
public static short littleEndianToShort(byte[] bs, int off)
{
int n = bs[ off] & 0xff;
n |= (bs[++off] & 0xff) << 8;
return (short)n;
}
public static void intToBigEndian(int n, byte[] bs, int off)
{
bs[ off] = (byte)(n >>> 24);
bs[++off] = (byte)(n >>> 16);
bs[++off] = (byte)(n >>> 8);
bs[++off] = (byte)(n );
}
}
RuntimeCryptoException.java 0000664 0000000 0000000 00000003514 13535653744 0034231 0 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* the foundation class for the exceptions thrown by the crypto packages.
*/
public class RuntimeCryptoException
extends RuntimeException
{
/**
* base constructor.
*/
public RuntimeCryptoException()
{
}
/**
* create a RuntimeCryptoException with the given message.
*
* @param message the message to be carried with the exception.
*/
public RuntimeCryptoException(
String message)
{
super(message);
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/SHA256Digest.java 0000664 0000000 0000000 00000023752 13535653744 0031623 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
/**
* FIPS 180-2 implementation of SHA-256.
*
*
*/
public class SHA256Digest
extends GeneralDigest
implements EncodableDigest
{
private static final int DIGEST_LENGTH = 32;
private int H1, H2, H3, H4, H5, H6, H7, H8;
private int[] X = new int[64];
private int xOff;
/**
* Standard constructor
*/
public SHA256Digest()
{
reset();
}
/**
* Copy constructor. This will copy the state of the provided
* message digest.
*/
public SHA256Digest(SHA256Digest t)
{
super(t);
copyIn(t);
}
private void copyIn(SHA256Digest t)
{
super.copyIn(t);
H1 = t.H1;
H2 = t.H2;
H3 = t.H3;
H4 = t.H4;
H5 = t.H5;
H6 = t.H6;
H7 = t.H7;
H8 = t.H8;
System.arraycopy(t.X, 0, X, 0, t.X.length);
xOff = t.xOff;
}
/**
* State constructor - create a digest initialised with the state of a previous one.
*
* @param encodedState the encoded state from the originating digest.
*/
public SHA256Digest(byte[] encodedState)
{
super(encodedState);
H1 = Pack.bigEndianToInt(encodedState, 16);
H2 = Pack.bigEndianToInt(encodedState, 20);
H3 = Pack.bigEndianToInt(encodedState, 24);
H4 = Pack.bigEndianToInt(encodedState, 28);
H5 = Pack.bigEndianToInt(encodedState, 32);
H6 = Pack.bigEndianToInt(encodedState, 36);
H7 = Pack.bigEndianToInt(encodedState, 40);
H8 = Pack.bigEndianToInt(encodedState, 44);
xOff = Pack.bigEndianToInt(encodedState, 48);
for (int i = 0; i != xOff; i++)
{
X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4));
}
}
public String getAlgorithmName()
{
return "SHA-256";
}
public int getDigestSize()
{
return DIGEST_LENGTH;
}
protected void processWord(
byte[] in,
int inOff)
{
// Note: Inlined for performance
// X[xOff] = Pack.bigEndianToInt(in, inOff);
int n = in[inOff] << 24;
n |= (in[++inOff] & 0xff) << 16;
n |= (in[++inOff] & 0xff) << 8;
n |= (in[++inOff] & 0xff);
X[xOff] = n;
if (++xOff == 16)
{
processBlock();
}
}
protected void processLength(
long bitLength)
{
if (xOff > 14)
{
processBlock();
}
X[14] = (int)(bitLength >>> 32);
X[15] = (int)(bitLength & 0xffffffff);
}
public int doFinal(
byte[] out,
int outOff)
{
finish();
Pack.intToBigEndian(H1, out, outOff);
Pack.intToBigEndian(H2, out, outOff + 4);
Pack.intToBigEndian(H3, out, outOff + 8);
Pack.intToBigEndian(H4, out, outOff + 12);
Pack.intToBigEndian(H5, out, outOff + 16);
Pack.intToBigEndian(H6, out, outOff + 20);
Pack.intToBigEndian(H7, out, outOff + 24);
Pack.intToBigEndian(H8, out, outOff + 28);
reset();
return DIGEST_LENGTH;
}
/**
* reset the chaining variables
*/
public void reset()
{
super.reset();
/* SHA-256 initial hash value
* The first 32 bits of the fractional parts of the square roots
* of the first eight prime numbers
*/
H1 = 0x6a09e667;
H2 = 0xbb67ae85;
H3 = 0x3c6ef372;
H4 = 0xa54ff53a;
H5 = 0x510e527f;
H6 = 0x9b05688c;
H7 = 0x1f83d9ab;
H8 = 0x5be0cd19;
xOff = 0;
for (int i = 0; i != X.length; i++)
{
X[i] = 0;
}
}
protected void processBlock()
{
//
// expand 16 word block into 64 word blocks.
//
for (int t = 16; t <= 63; t++)
{
X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16];
}
//
// set up working variables.
//
int a = H1;
int b = H2;
int c = H3;
int d = H4;
int e = H5;
int f = H6;
int g = H7;
int h = H8;
int t = 0;
for(int i = 0; i < 8; i ++)
{
// t = 8 * i
h += Sum1(e) + Ch(e, f, g) + K[t] + X[t];
d += h;
h += Sum0(a) + Maj(a, b, c);
++t;
// t = 8 * i + 1
g += Sum1(d) + Ch(d, e, f) + K[t] + X[t];
c += g;
g += Sum0(h) + Maj(h, a, b);
++t;
// t = 8 * i + 2
f += Sum1(c) + Ch(c, d, e) + K[t] + X[t];
b += f;
f += Sum0(g) + Maj(g, h, a);
++t;
// t = 8 * i + 3
e += Sum1(b) + Ch(b, c, d) + K[t] + X[t];
a += e;
e += Sum0(f) + Maj(f, g, h);
++t;
// t = 8 * i + 4
d += Sum1(a) + Ch(a, b, c) + K[t] + X[t];
h += d;
d += Sum0(e) + Maj(e, f, g);
++t;
// t = 8 * i + 5
c += Sum1(h) + Ch(h, a, b) + K[t] + X[t];
g += c;
c += Sum0(d) + Maj(d, e, f);
++t;
// t = 8 * i + 6
b += Sum1(g) + Ch(g, h, a) + K[t] + X[t];
f += b;
b += Sum0(c) + Maj(c, d, e);
++t;
// t = 8 * i + 7
a += Sum1(f) + Ch(f, g, h) + K[t] + X[t];
e += a;
a += Sum0(b) + Maj(b, c, d);
++t;
}
H1 += a;
H2 += b;
H3 += c;
H4 += d;
H5 += e;
H6 += f;
H7 += g;
H8 += h;
//
// reset the offset and clean out the word buffer.
//
xOff = 0;
for (int i = 0; i < 16; i++)
{
X[i] = 0;
}
}
/* SHA-256 functions */
private int Ch(
int x,
int y,
int z)
{
return (x & y) ^ ((~x) & z);
}
private int Maj(
int x,
int y,
int z)
{
return (x & y) ^ (x & z) ^ (y & z);
}
private int Sum0(
int x)
{
return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10));
}
private int Sum1(
int x)
{
return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7));
}
private int Theta0(
int x)
{
return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3);
}
private int Theta1(
int x)
{
return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10);
}
/* SHA-256 Constants
* (represent the first 32 bits of the fractional parts of the
* cube roots of the first sixty-four prime numbers)
*/
static final int K[] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
public Memoable copy()
{
return new SHA256Digest(this);
}
public void reset(Memoable other)
{
SHA256Digest d = (SHA256Digest)other;
copyIn(d);
}
public byte[] getEncodedState()
{
byte[] state = new byte[52 + xOff * 4];
super.populateState(state);
Pack.intToBigEndian(H1, state, 16);
Pack.intToBigEndian(H2, state, 20);
Pack.intToBigEndian(H3, state, 24);
Pack.intToBigEndian(H4, state, 28);
Pack.intToBigEndian(H5, state, 32);
Pack.intToBigEndian(H6, state, 36);
Pack.intToBigEndian(H7, state, 40);
Pack.intToBigEndian(H8, state, 44);
Pack.intToBigEndian(xOff, state, 48);
for (int i = 0; i != xOff; i++)
{
Pack.intToBigEndian(X[i], state, 52 + (i * 4));
}
return state;
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/bouncycastle/pbkdf2/Strings.java 0000664 0000000 0000000 00000010346 13535653744 0031237 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.bouncycastle.pbkdf2;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* String utilities.
*/
public final class Strings
{
public static byte[] toUTF8ByteArray(char[] string)
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
try
{
toUTF8ByteArray(string, bOut);
}
catch (IOException e)
{
throw new IllegalStateException("cannot encode string to byte array!");
}
return bOut.toByteArray();
}
public static void toUTF8ByteArray(char[] string, OutputStream sOut)
throws IOException
{
char[] c = string;
int i = 0;
while (i < c.length)
{
char ch = c[i];
if (ch < 0x0080)
{
sOut.write(ch);
}
else if (ch < 0x0800)
{
sOut.write(0xc0 | (ch >> 6));
sOut.write(0x80 | (ch & 0x3f));
}
// surrogate pair
else if (ch >= 0xD800 && ch <= 0xDFFF)
{
// in error - can only happen, if the Java String class has a
// bug.
if (i + 1 >= c.length)
{
throw new IllegalStateException("invalid UTF-16 codepoint");
}
char W1 = ch;
ch = c[++i];
char W2 = ch;
// in error - can only happen, if the Java String class has a
// bug.
if (W1 > 0xDBFF)
{
throw new IllegalStateException("invalid UTF-16 codepoint");
}
int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000;
sOut.write(0xf0 | (codePoint >> 18));
sOut.write(0x80 | ((codePoint >> 12) & 0x3F));
sOut.write(0x80 | ((codePoint >> 6) & 0x3F));
sOut.write(0x80 | (codePoint & 0x3F));
}
else
{
sOut.write(0xe0 | (ch >> 12));
sOut.write(0x80 | ((ch >> 6) & 0x3F));
sOut.write(0x80 | (ch & 0x3F));
}
i++;
}
}
/**
* Convert an array of 8 bit characters into a string.
*
* @param bytes 8 bit characters.
* @return resulting String.
*/
public static String fromByteArray(byte[] bytes)
{
return new String(asCharArray(bytes));
}
/**
* Do a simple conversion of an array of 8 bit characters into a string.
*
* @param bytes 8 bit characters.
* @return resulting String.
*/
public static char[] asCharArray(byte[] bytes)
{
char[] chars = new char[bytes.length];
for (int i = 0; i != chars.length; i++)
{
chars[i] = (char)(bytes[i] & 0xff);
}
return chars;
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/exception/ 0000775 0000000 0000000 00000000000 13535653744 0025072 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/exception/ScramException.java 0000664 0000000 0000000 00000004104 13535653744 0030660 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.exception;
import javax.security.sasl.SaslException;
/**
* This class represents an error when using SCRAM, which is a SASL method.
*
* {@link SaslException}
*/
public class ScramException extends SaslException {
/**
* Constructs a new instance of ScramException with a detailed message.
* @param detail A String containing details about the exception
*/
public ScramException(String detail) {
super(detail);
}
/**
* Constructs a new instance of ScramException with a detailed message and a root cause.
* @param detail A String containing details about the exception
* @param ex The root exception
*/
public ScramException(String detail, Throwable ex) {
super(detail, ex);
}
}
ScramInvalidServerSignatureException.java 0000664 0000000 0000000 00000004135 13535653744 0035165 0 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/exception /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.exception;
/**
* This class represents an error when parsing SCRAM messages
*/
public class ScramInvalidServerSignatureException extends ScramException {
/**
* Constructs a new instance of ScramInvalidServerSignatureException with a detailed message.
* @param detail A String containing details about the exception
*/
public ScramInvalidServerSignatureException(String detail) {
super(detail);
}
/**
* Constructs a new instance of ScramInvalidServerSignatureException with a detailed message and a root cause.
* @param detail A String containing details about the exception
* @param ex The root exception
*/
public ScramInvalidServerSignatureException(String detail, Throwable ex) {
super(detail, ex);
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/exception/ScramParseException.java 0000664 0000000 0000000 00000004010 13535653744 0031647 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.exception;
/**
* This class represents an error when parsing SCRAM messages
*/
public class ScramParseException extends ScramException {
/**
* Constructs a new instance of ScramParseException with a detailed message.
* @param detail A String containing details about the exception
*/
public ScramParseException(String detail) {
super(detail);
}
/**
* Constructs a new instance of ScramParseException with a detailed message and a root cause.
* @param detail A String containing details about the exception
* @param ex The root exception
*/
public ScramParseException(String detail, Throwable ex) {
super(detail, ex);
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/exception/ScramServerErrorException.java 0000664 0000000 0000000 00000004726 13535653744 0033073 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.exception;
import com.ongres.scram.common.message.ServerFinalMessage;
/**
* This class represents an error when parsing SCRAM messages
*/
public class ScramServerErrorException extends ScramException {
private final ServerFinalMessage.Error error;
private static String toString(ServerFinalMessage.Error error) {
return "Server-final-message is an error message. Error: " + error.getErrorMessage();
}
/**
* Constructs a new instance of ScramServerErrorException with a detailed message.
* @param error The SCRAM error in the message
*/
public ScramServerErrorException(ServerFinalMessage.Error error) {
super(toString(error));
this.error = error;
}
/**
* Constructs a new instance of ScramServerErrorException with a detailed message and a root cause.
* @param error The SCRAM error in the message
* @param ex The root exception
*/
public ScramServerErrorException(ServerFinalMessage.Error error, Throwable ex) {
super(toString(error), ex);
this.error = error;
}
public ServerFinalMessage.Error getError() {
return error;
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/gssapi/ 0000775 0000000 0000000 00000000000 13535653744 0024362 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/gssapi/Gs2AttributeValue.java 0000664 0000000 0000000 00000005161 13535653744 0030544 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.gssapi;
import com.ongres.scram.common.util.AbstractCharAttributeValue;
/**
* Parse and write GS2 Attribute-Value pairs.
*/
public class Gs2AttributeValue extends AbstractCharAttributeValue {
public Gs2AttributeValue(Gs2Attributes attribute, String value) {
super(attribute, value);
}
public static StringBuffer writeTo(StringBuffer sb, Gs2Attributes attribute, String value) {
return new Gs2AttributeValue(attribute, value).writeTo(sb);
}
/**
* Parses a potential Gs2AttributeValue String.
* @param value The string that contains the Attribute-Value pair (where value is optional).
* @return The parsed class, or null if the String was null.
* @throws IllegalArgumentException If the String is an invalid Gs2AttributeValue
*/
public static Gs2AttributeValue parse(String value) throws IllegalArgumentException {
if(null == value) {
return null;
}
if(value.length() < 1 || value.length() == 2 || (value.length() > 2 && value.charAt(1) != '=')) {
throw new IllegalArgumentException("Invalid Gs2AttributeValue");
}
return new Gs2AttributeValue(
Gs2Attributes.byChar(value.charAt(0)),
value.length() > 2 ? value.substring(2) : null
);
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/gssapi/Gs2Attributes.java 0000664 0000000 0000000 00000005677 13535653744 0027746 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.gssapi;
import com.ongres.scram.common.ScramAttributes;
import com.ongres.scram.common.util.CharAttribute;
/**
* Possible values of a GS2 Attribute.
*
* @see [RFC5802] Formal Syntax
*/
public enum Gs2Attributes implements CharAttribute {
/**
* Channel binding attribute. Client doesn't support channel binding.
*/
CLIENT_NOT(Gs2CbindFlag.CLIENT_NOT.getChar()),
/**
* Channel binding attribute. Client does support channel binding but thinks the server does not.
*/
CLIENT_YES_SERVER_NOT(Gs2CbindFlag.CLIENT_YES_SERVER_NOT.getChar()),
/**
* Channel binding attribute. Client requires channel binding. The selected channel binding follows "p=".
*/
CHANNEL_BINDING_REQUIRED(Gs2CbindFlag.CHANNEL_BINDING_REQUIRED.getChar()),
/**
* SCRAM attribute. This attribute specifies an authorization identity.
*/
AUTHZID(ScramAttributes.AUTHZID.getChar())
;
private final char flag;
Gs2Attributes(char flag) {
this.flag = flag;
}
@Override
public char getChar() {
return flag;
}
public static Gs2Attributes byChar(char c) {
switch(c) {
case 'n': return CLIENT_NOT;
case 'y': return CLIENT_YES_SERVER_NOT;
case 'p': return CHANNEL_BINDING_REQUIRED;
case 'a': return AUTHZID;
}
throw new IllegalArgumentException("Invalid GS2Attribute character '" + c + "'");
}
public static Gs2Attributes byGS2CbindFlag(Gs2CbindFlag cbindFlag) {
return byChar(cbindFlag.getChar());
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/gssapi/Gs2CbindFlag.java 0000664 0000000 0000000 00000005024 13535653744 0027413 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.gssapi;
import com.ongres.scram.common.util.CharAttribute;
/**
* Possible values of a GS2 Cbind Flag (channel binding; part of GS2 header).
* These values are sent by the client, and so are interpreted from this perspective.
*
* @see [RFC5802] Formal Syntax
*/
public enum Gs2CbindFlag implements CharAttribute {
/**
* Client doesn't support channel binding.
*/
CLIENT_NOT('n'),
/**
* Client does support channel binding but thinks the server does not.
*/
CLIENT_YES_SERVER_NOT('y'),
/**
* Client requires channel binding. The selected channel binding follows "p=".
*/
CHANNEL_BINDING_REQUIRED('p')
;
private final char flag;
Gs2CbindFlag(char flag) {
this.flag = flag;
}
@Override
public char getChar() {
return flag;
}
public static Gs2CbindFlag byChar(char c) {
switch(c) {
case 'n': return CLIENT_NOT;
case 'y': return CLIENT_YES_SERVER_NOT;
case 'p': return CHANNEL_BINDING_REQUIRED;
}
throw new IllegalArgumentException("Invalid Gs2CbindFlag character '" + c + "'");
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/gssapi/Gs2Header.java 0000664 0000000 0000000 00000013056 13535653744 0026776 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.gssapi;
import com.ongres.scram.common.util.StringWritableCsv;
import com.ongres.scram.common.ScramStringFormatting;
import com.ongres.scram.common.util.AbstractStringWritable;
import static com.ongres.scram.common.util.Preconditions.checkNotNull;
/**
* GSS Header. Format:
*
* {@code
* gs2-header = gs2-cbind-flag "," [ authzid ] ","
* gs2-cbind-flag = ("p=" cb-name) / "n" / "y"
* authzid = "a=" saslname
* }
*
* Current implementation does not support channel binding.
* If p is used as the cbind flag, the cb-name value is not validated.
*
* @see [RFC5802] Formal Syntax
*/
public class Gs2Header extends AbstractStringWritable {
private final Gs2AttributeValue cbind;
private final Gs2AttributeValue authzid;
/**
* Construct and validates a Gs2Header.
* Only provide the channel binding name if the channel binding flag is set to required.
* @param cbindFlag The channel binding flag
* @param cbName The channel-binding name. Should be not null iif channel binding is required
* @param authzid The optional SASL authorization identity
* @throws IllegalArgumentException If the channel binding flag and argument are invalid
*/
public Gs2Header(Gs2CbindFlag cbindFlag, String cbName, String authzid) throws IllegalArgumentException {
checkNotNull(cbindFlag, "cbindFlag");
if(cbindFlag == Gs2CbindFlag.CHANNEL_BINDING_REQUIRED ^ cbName != null) {
throw new IllegalArgumentException("Specify channel binding flag and value together, or none");
}
// TODO: cbName is not being properly validated
cbind = new Gs2AttributeValue(Gs2Attributes.byGS2CbindFlag(cbindFlag), cbName);
this.authzid = authzid == null ?
null : new Gs2AttributeValue(Gs2Attributes.AUTHZID, ScramStringFormatting.toSaslName(authzid))
;
}
/**
* Construct and validates a Gs2Header with no authzid.
* Only provide the channel binding name if the channel binding flag is set to required.
* @param cbindFlag The channel binding flag
* @param cbName The channel-binding name. Should be not null iif channel binding is required
* @throws IllegalArgumentException If the channel binding flag and argument are invalid
*/
public Gs2Header(Gs2CbindFlag cbindFlag, String cbName) throws IllegalArgumentException {
this(cbindFlag, cbName, null);
}
/**
* Construct and validates a Gs2Header with no authzid nor channel binding.
* @param cbindFlag The channel binding flag
* @throws IllegalArgumentException If the channel binding is supported (no cbname can be provided here)
*/
public Gs2Header(Gs2CbindFlag cbindFlag) {
this(cbindFlag, null, null);
}
public Gs2CbindFlag getChannelBindingFlag() {
return Gs2CbindFlag.byChar(cbind.getChar());
}
public String getChannelBindingName() {
return cbind.getValue();
}
public String getAuthzid() {
return authzid != null ? authzid.getValue() : null;
}
@Override
public StringBuffer writeTo(StringBuffer sb) {
return StringWritableCsv.writeTo(sb, cbind, authzid);
}
/**
* Read a Gs2Header from a String. String may contain trailing fields that will be ignored.
* @param message The String containing the Gs2Header
* @return The parsed Gs2Header object
* @throws IllegalArgumentException If the format/values of the String do not conform to a Gs2Header
*/
public static Gs2Header parseFrom(String message) throws IllegalArgumentException {
checkNotNull(message, "Null message");
String[] gs2HeaderSplit = StringWritableCsv.parseFrom(message, 2);
if(gs2HeaderSplit.length == 0) {
throw new IllegalArgumentException("Invalid number of fields for the GS2 Header");
}
Gs2AttributeValue gs2cbind = Gs2AttributeValue.parse(gs2HeaderSplit[0]);
return new Gs2Header(
Gs2CbindFlag.byChar(gs2cbind.getChar()),
gs2cbind.getValue(),
gs2HeaderSplit[1] == null || gs2HeaderSplit[1].isEmpty() ?
null : Gs2AttributeValue.parse(gs2HeaderSplit[1]).getValue()
);
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/message/ 0000775 0000000 0000000 00000000000 13535653744 0024520 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/message/ClientFinalMessage.java 0000664 0000000 0000000 00000012677 13535653744 0031075 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.message;
import com.ongres.scram.common.ScramAttributeValue;
import com.ongres.scram.common.ScramAttributes;
import com.ongres.scram.common.ScramStringFormatting;
import com.ongres.scram.common.gssapi.Gs2Header;
import com.ongres.scram.common.util.StringWritable;
import com.ongres.scram.common.util.StringWritableCsv;
import static com.ongres.scram.common.util.Preconditions.checkNotEmpty;
import static com.ongres.scram.common.util.Preconditions.checkNotNull;
/**
* Constructs and parses client-final-messages. Formal syntax is:
*
* {@code
* client-final-message-without-proof = channel-binding "," nonce ["," extensions]
* client-final-message = client-final-message-without-proof "," proof
* }
*
* Note that extensions are not supported.
*
* @see [RFC5802] Section 7
*/
public class ClientFinalMessage implements StringWritable {
private final String cbind;
private final String nonce;
private final byte[] proof;
private static String generateCBind(Gs2Header gs2Header, byte[] cbindData) {
StringBuffer sb = new StringBuffer();
gs2Header.writeTo(sb)
.append(',');
if(null != cbindData) {
new ScramAttributeValue(
ScramAttributes.CHANNEL_BINDING,
ScramStringFormatting.base64Encode(cbindData)
).writeTo(sb);
}
return sb.toString();
}
/**
* Constructus a client-final-message with the provided gs2Header (the same one used in the client-first-message),
* optionally the channel binding data, and the nonce.
* This method is intended to be used by SCRAM clients, and not to be constructed directly.
* @param gs2Header The GSS-API header
* @param cbindData If using channel binding, the channel binding data
* @param nonce The nonce
* @param proof The bytes representing the computed client proof
*/
public ClientFinalMessage(Gs2Header gs2Header, byte[] cbindData, String nonce, byte[] proof) {
this.cbind = generateCBind(
checkNotNull(gs2Header, "gs2Header"),
cbindData
);
this.nonce = checkNotEmpty(nonce, "nonce");
this.proof = checkNotNull(proof, "proof");
}
private static StringBuffer writeToWithoutProof(StringBuffer sb, String cbind, String nonce) {
return StringWritableCsv.writeTo(
sb,
new ScramAttributeValue(ScramAttributes.CHANNEL_BINDING, ScramStringFormatting.base64Encode(cbind)),
new ScramAttributeValue(ScramAttributes.NONCE, nonce)
);
}
private static StringBuffer writeToWithoutProof(
StringBuffer sb, Gs2Header gs2Header, byte[] cbindData, String nonce
) {
return writeToWithoutProof(
sb,
generateCBind(
checkNotNull(gs2Header, "gs2Header"),
cbindData
),
nonce
);
}
/**
* Returns a StringBuffer filled in with the formatted output of a client-first-message without the proof value.
* This is useful for computing the auth-message, used in turn to compute the proof.
* @param gs2Header The GSS-API header
* @param cbindData The optional channel binding data
* @param nonce The nonce
* @return The String representation of the part of the message that excludes the proof
*/
public static StringBuffer writeToWithoutProof(Gs2Header gs2Header, byte[] cbindData, String nonce) {
return writeToWithoutProof(new StringBuffer(), gs2Header, cbindData, nonce);
}
@Override
public StringBuffer writeTo(StringBuffer sb) {
writeToWithoutProof(sb, cbind, nonce);
return StringWritableCsv.writeTo(
sb,
null, // This marks the position of writeToWithoutProof, required for the ","
new ScramAttributeValue(ScramAttributes.CLIENT_PROOF, ScramStringFormatting.base64Encode(proof))
);
}
@Override
public String toString() {
return writeTo(new StringBuffer()).toString();
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/message/ClientFirstMessage.java 0000664 0000000 0000000 00000020600 13535653744 0031114 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.message;
import com.ongres.scram.common.ScramAttributeValue;
import com.ongres.scram.common.ScramAttributes;
import com.ongres.scram.common.ScramStringFormatting;
import com.ongres.scram.common.exception.ScramParseException;
import com.ongres.scram.common.gssapi.Gs2CbindFlag;
import com.ongres.scram.common.gssapi.Gs2Header;
import com.ongres.scram.common.util.StringWritable;
import com.ongres.scram.common.util.StringWritableCsv;
import static com.ongres.scram.common.util.Preconditions.checkNotEmpty;
import static com.ongres.scram.common.util.Preconditions.checkNotNull;
/**
* Constructs and parses client-first-messages.
* Message contains a {@link Gs2Header}, a username and a nonce. Formal syntax is:
*
* {@code
* client-first-message-bare = [reserved-mext ","] username "," nonce ["," extensions]
client-first-message = gs2-header client-first-message-bare
* }
*
* Note that extensions are not supported.
*
* @see [RFC5802] Section 7
*/
public class ClientFirstMessage implements StringWritable {
private final Gs2Header gs2Header;
private final String user;
private final String nonce;
/**
* Constructs a client-first-message for the given user, nonce and gs2Header.
* This constructor is intended to be instantiated by a scram client, and not directly.
* The client should be providing the header, and nonce (and probably the user too).
* @param gs2Header The GSS-API header
* @param user The SCRAM user
* @param nonce The nonce for this session
* @throws IllegalArgumentException If any of the arguments is null or empty
*/
public ClientFirstMessage(Gs2Header gs2Header, String user, String nonce) throws IllegalArgumentException {
this.gs2Header = checkNotNull(gs2Header, "gs2Header");
this.user = checkNotEmpty(user, "user");
this.nonce = checkNotEmpty(nonce, "nonce");
}
private static Gs2Header gs2Header(Gs2CbindFlag gs2CbindFlag, String authzid, String cbindName) {
checkNotNull(gs2CbindFlag, "gs2CbindFlag");
if(Gs2CbindFlag.CHANNEL_BINDING_REQUIRED == gs2CbindFlag && null == cbindName) {
throw new IllegalArgumentException("Channel binding name is required if channel binding is specified");
}
return new Gs2Header(gs2CbindFlag, cbindName, authzid);
}
/**
* Constructs a client-first-message for the given parameters.
* Under normal operation, this constructor is intended to be instantiated by a scram client, and not directly.
* However, this constructor is more user- or test-friendly, as the arguments are easier to provide without
* building other indirect object parameters.
* @param gs2CbindFlag The channel-binding flag
* @param authzid The optional authzid
* @param cbindName The optional channel binding name
* @param user The SCRAM user
* @param nonce The nonce for this session
* @throws IllegalArgumentException If the flag, user or nonce are null or empty
*/
public ClientFirstMessage(Gs2CbindFlag gs2CbindFlag, String authzid, String cbindName, String user, String nonce) {
this(gs2Header(gs2CbindFlag, authzid, cbindName), user, nonce);
}
/**
* Constructs a client-first-message for the given parameters, with no channel binding nor authzid.
* Under normal operation, this constructor is intended to be instantiated by a scram client, and not directly.
* However, this constructor is more user- or test-friendly, as the arguments are easier to provide without
* building other indirect object parameters.
* @param user The SCRAM user
* @param nonce The nonce for this session
* @throws IllegalArgumentException If the user or nonce are null or empty
*/
public ClientFirstMessage(String user, String nonce) {
this(gs2Header(Gs2CbindFlag.CLIENT_NOT, null, null), user, nonce);
}
public Gs2CbindFlag getChannelBindingFlag() {
return gs2Header.getChannelBindingFlag();
}
public boolean isChannelBinding() {
return gs2Header.getChannelBindingFlag() == Gs2CbindFlag.CHANNEL_BINDING_REQUIRED;
}
public String getChannelBindingName() {
return gs2Header.getChannelBindingName();
}
public String getAuthzid() {
return gs2Header.getAuthzid();
}
public Gs2Header getGs2Header() {
return gs2Header;
}
public String getUser() {
return user;
}
public String getNonce() {
return nonce;
}
/**
* Limited version of the {@link StringWritableCsv#toString()} method, that doesn't write the GS2 header.
* This method is useful to construct the auth message used as part of the SCRAM algorithm.
* @param sb A StringBuffer where to write the data to.
* @return The same StringBuffer
*/
public StringBuffer writeToWithoutGs2Header(StringBuffer sb) {
return StringWritableCsv.writeTo(
sb,
new ScramAttributeValue(ScramAttributes.USERNAME, ScramStringFormatting.toSaslName(user)),
new ScramAttributeValue(ScramAttributes.NONCE, nonce)
);
}
@Override
public StringBuffer writeTo(StringBuffer sb) {
StringWritableCsv.writeTo(
sb,
gs2Header,
null // This marks the position of the rest of the elements, required for the ","
);
return writeToWithoutGs2Header(sb);
}
/**
* Construct a {@link ClientFirstMessage} instance from a message (String)
* @param clientFirstMessage The String representing the client-first-message
* @return The instance
* @throws ScramParseException If the message is not a valid client-first-message
* @throws IllegalArgumentException If the message is null or empty
*/
public static ClientFirstMessage parseFrom(String clientFirstMessage)
throws ScramParseException, IllegalArgumentException {
checkNotEmpty(clientFirstMessage, "clientFirstMessage");
Gs2Header gs2Header = Gs2Header.parseFrom(clientFirstMessage); // Takes first two fields
String[] userNonceString;
try {
userNonceString = StringWritableCsv.parseFrom(clientFirstMessage, 2, 2);
} catch (IllegalArgumentException e) {
throw new ScramParseException("Illegal series of attributes in client-first-message", e);
}
ScramAttributeValue user = ScramAttributeValue.parse(userNonceString[0]);
if(ScramAttributes.USERNAME.getChar() != user.getChar()) {
throw new ScramParseException("user must be the 3rd element of the client-first-message");
}
ScramAttributeValue nonce = ScramAttributeValue.parse(userNonceString[1]);
if(ScramAttributes.NONCE.getChar() != nonce.getChar()) {
throw new ScramParseException("nonce must be the 4th element of the client-first-message");
}
return new ClientFirstMessage(gs2Header, user.getValue(), nonce.getValue());
}
@Override
public String toString() {
return writeTo(new StringBuffer()).toString();
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/message/ServerFinalMessage.java 0000664 0000000 0000000 00000020651 13535653744 0031114 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.message;
import static com.ongres.scram.common.util.Preconditions.checkNotEmpty;
import static com.ongres.scram.common.util.Preconditions.checkNotNull;
import java.util.HashMap;
import java.util.Map;
import com.ongres.scram.common.ScramAttributeValue;
import com.ongres.scram.common.ScramAttributes;
import com.ongres.scram.common.ScramStringFormatting;
import com.ongres.scram.common.exception.ScramParseException;
import com.ongres.scram.common.util.StringWritable;
import com.ongres.scram.common.util.StringWritableCsv;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* Constructs and parses server-final-messages. Formal syntax is:
*
* {@code
* server-error = "e=" server-error-value
*
* server-error-value = "invalid-encoding" /
* "extensions-not-supported" / ; unrecognized 'm' value
* "invalid-proof" /
* "channel-bindings-dont-match" /
* "server-does-support-channel-binding" /
* ; server does not support channel binding
* "channel-binding-not-supported" /
* "unsupported-channel-binding-type" /
* "unknown-user" /
* "invalid-username-encoding" /
* ; invalid username encoding (invalid UTF-8 or
* ; SASLprep failed)
* "no-resources" /
* "other-error" /
* server-error-value-ext
* ; Unrecognized errors should be treated as "other-error".
* ; In order to prevent information disclosure, the server
* ; may substitute the real reason with "other-error".
*
* server-error-value-ext = value
* ; Additional error reasons added by extensions
* ; to this document.
*
* verifier = "v=" base64
* ;; base-64 encoded ServerSignature.
*
* server-final-errorMessage = (server-error / verifier)
* ["," extensions]
* }
*
* Note that extensions are not supported (and, consequently, error message extensions).
*
* @see [RFC5802] Section 7
*/
public class ServerFinalMessage implements StringWritable {
/**
* Possible error messages sent on a server-final-message.
*/
public enum Error {
INVALID_ENCODING("invalid-encoding"),
EXTENSIONS_NOT_SUPPORTED("extensions-not-supported"),
INVALID_PROOF("invalid-proof"),
CHANNEL_BINDINGS_DONT_MATCH("channel-bindings-dont-match"),
SERVER_DOES_SUPPORT_CHANNEL_BINDING("server-does-support-channel-binding"),
CHANNEL_BINDING_NOT_SUPPORTED("channel-binding-not-supported"),
UNSUPPORTED_CHANNEL_BINDING_TYPE("unsupported-channel-binding-type"),
UNKNOWN_USER("unknown-user"),
INVALID_USERNAME_ENCODING("invalid-username-encoding"),
NO_RESOURCES("no-resources"),
OTHER_ERROR("other-error")
;
private static final Map BY_NAME_MAPPING = valuesAsMap();
private final String errorMessage;
Error(String errorMessage) {
this.errorMessage = errorMessage;
}
public String getErrorMessage() {
return errorMessage;
}
public static Error getByErrorMessage(String errorMessage) throws IllegalArgumentException {
checkNotEmpty(errorMessage, "errorMessage");
if(! BY_NAME_MAPPING.containsKey(errorMessage)) {
throw new IllegalArgumentException("Invalid error message '" + errorMessage + "'");
}
return BY_NAME_MAPPING.get(errorMessage);
}
private static Map valuesAsMap() {
Map map = new HashMap<>(values().length);
for (Error error : values()) {
map.put(error.errorMessage, error);
}
return map;
}
}
private final byte[] verifier;
private final Error error;
/**
* Constructs a server-final-message with no errors, and the provided server verifier
* @param verifier The bytes of the computed signature
* @throws IllegalArgumentException If the verifier is null
*/
public ServerFinalMessage(byte[] verifier) throws IllegalArgumentException {
this.verifier = checkNotNull(verifier, "verifier");
this.error = null;
}
/**
* Constructs a server-final-message which represents a SCRAM error.
* @param error The error
* @throws IllegalArgumentException If the error is null
*/
public ServerFinalMessage(Error error) throws IllegalArgumentException {
this.error = checkNotNull(error, "error");
this.verifier = null;
}
/**
* Whether this server-final-message contains an error
* @return True if it contains an error, false if it contains a verifier
*/
public boolean isError() {
return null != error;
}
@SuppressFBWarnings("EI_EXPOSE_REP")
public byte[] getVerifier() {
return verifier;
}
public Error getError() {
return error;
}
@Override
public StringBuffer writeTo(StringBuffer sb) {
return StringWritableCsv.writeTo(
sb,
isError() ?
new ScramAttributeValue(ScramAttributes.ERROR, error.errorMessage)
: new ScramAttributeValue(
ScramAttributes.SERVER_SIGNATURE, ScramStringFormatting.base64Encode(verifier)
)
);
}
/**
* Parses a server-final-message from a String.
* @param serverFinalMessage The message
* @return A constructed server-final-message instance
* @throws ScramParseException If the argument is not a valid server-final-message
* @throws IllegalArgumentException If the message is null or empty
*/
public static ServerFinalMessage parseFrom(String serverFinalMessage)
throws ScramParseException, IllegalArgumentException {
checkNotEmpty(serverFinalMessage, "serverFinalMessage");
String[] attributeValues = StringWritableCsv.parseFrom(serverFinalMessage, 1, 0);
if(attributeValues == null || attributeValues.length != 1) {
throw new ScramParseException("Invalid server-final-message");
}
ScramAttributeValue attributeValue = ScramAttributeValue.parse(attributeValues[0]);
if(ScramAttributes.SERVER_SIGNATURE.getChar() == attributeValue.getChar()) {
byte[] verifier = ScramStringFormatting.base64Decode(attributeValue.getValue());
return new ServerFinalMessage(verifier);
} else if(ScramAttributes.ERROR.getChar() == attributeValue.getChar()) {
return new ServerFinalMessage(Error.getByErrorMessage(attributeValue.getValue()));
} else {
throw new ScramParseException(
"Invalid server-final-message: it must contain either a verifier or an error attribute"
);
}
}
@Override
public String toString() {
return writeTo(new StringBuffer()).toString();
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/message/ServerFirstMessage.java 0000664 0000000 0000000 00000014721 13535653744 0031153 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.message;
import com.ongres.scram.common.ScramAttributeValue;
import com.ongres.scram.common.ScramAttributes;
import com.ongres.scram.common.exception.ScramParseException;
import com.ongres.scram.common.util.StringWritable;
import com.ongres.scram.common.util.StringWritableCsv;
import static com.ongres.scram.common.util.Preconditions.checkArgument;
import static com.ongres.scram.common.util.Preconditions.checkNotEmpty;
/**
* Constructs and parses server-first-messages. Formal syntax is:
*
* {@code
* server-first-message = [reserved-mext ","] nonce "," salt ","
* iteration-count ["," extensions]
* }
*
* Note that extensions are not supported.
*
* @see [RFC5802] Section 7
*/
public class ServerFirstMessage implements StringWritable {
/**
* Minimum allowed value for the iteration, as per the RFC.
*/
public static final int ITERATION_MIN_VALUE = 4096;
private final String clientNonce;
private final String serverNonce;
private final String salt;
private final int iteration;
/**
* Constructs a server-first-message from a client-first-message and the additional required data.
* @param clientNonce String representing the client-first-message
* @param serverNonce Server serverNonce
* @param salt The salt
* @param iteration The iteration count (must be <= 4096)
* @throws IllegalArgumentException If clientFirstMessage, serverNonce or salt are null or empty,
* or iteration < 4096
*/
public ServerFirstMessage(
String clientNonce, String serverNonce, String salt, int iteration
) throws IllegalArgumentException {
this.clientNonce = checkNotEmpty(clientNonce, "clientNonce");
this.serverNonce = checkNotEmpty(serverNonce, "serverNonce");
this.salt = checkNotEmpty(salt, "salt");
checkArgument(iteration >= ITERATION_MIN_VALUE, "iteration must be >= " + ITERATION_MIN_VALUE);
this.iteration = iteration;
}
public String getClientNonce() {
return clientNonce;
}
public String getServerNonce() {
return serverNonce;
}
public String getNonce() {
return clientNonce + serverNonce;
}
public String getSalt() {
return salt;
}
public int getIteration() {
return iteration;
}
@Override
public StringBuffer writeTo(StringBuffer sb) {
return StringWritableCsv.writeTo(
sb,
new ScramAttributeValue(ScramAttributes.NONCE, getNonce()),
new ScramAttributeValue(ScramAttributes.SALT, salt),
new ScramAttributeValue(ScramAttributes.ITERATION, iteration + "")
);
}
/**
* Parses a server-first-message from a String.
* @param serverFirstMessage The string representing the server-first-message
* @param clientNonce The serverNonce that is present in the client-first-message
* @return The parsed instance
* @throws ScramParseException If the argument is not a valid server-first-message
* @throws IllegalArgumentException If either argument is empty or serverFirstMessage is not a valid message
*/
public static ServerFirstMessage parseFrom(String serverFirstMessage, String clientNonce)
throws ScramParseException, IllegalArgumentException {
checkNotEmpty(serverFirstMessage, "serverFirstMessage");
checkNotEmpty(clientNonce, "clientNonce");
String[] attributeValues = StringWritableCsv.parseFrom(serverFirstMessage, 3, 0);
if(attributeValues.length != 3) {
throw new ScramParseException("Invalid server-first-message");
}
ScramAttributeValue nonce = ScramAttributeValue.parse(attributeValues[0]);
if(ScramAttributes.NONCE.getChar() != nonce.getChar()) {
throw new ScramParseException("serverNonce must be the 1st element of the server-first-message");
}
if(! nonce.getValue().startsWith(clientNonce)) {
throw new ScramParseException("parsed serverNonce does not start with client serverNonce");
}
ScramAttributeValue salt = ScramAttributeValue.parse(attributeValues[1]);
if(ScramAttributes.SALT.getChar() != salt.getChar()) {
throw new ScramParseException("salt must be the 2nd element of the server-first-message");
}
ScramAttributeValue iteration = ScramAttributeValue.parse(attributeValues[2]);
if(ScramAttributes.ITERATION.getChar() != iteration.getChar()) {
throw new ScramParseException("iteration must be the 3rd element of the server-first-message");
}
int iterationInt;
try {
iterationInt = Integer.parseInt(iteration.getValue());
} catch (NumberFormatException e) {
throw new ScramParseException("invalid iteration");
}
return new ServerFirstMessage(
clientNonce, nonce.getValue().substring(clientNonce.length()), salt.getValue(), iterationInt
);
}
@Override
public String toString() {
return writeTo(new StringBuffer()).toString();
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/stringprep/ 0000775 0000000 0000000 00000000000 13535653744 0025271 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/stringprep/StringPreparation.java 0000664 0000000 0000000 00000003402 13535653744 0031606 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.stringprep;
/**
* Interface for all possible String Preparations mechanisms.
*/
public interface StringPreparation {
/**
* Normalize a UTF-8 String according to this String Preparation rules.
* @param value The String to prepare
* @return The prepared String
* @throws IllegalArgumentException If the String to prepare is not valid.
*/
String normalize(String value) throws IllegalArgumentException;
}
scram-2.1/common/src/main/java/com/ongres/scram/common/stringprep/StringPreparations.java 0000664 0000000 0000000 00000006111 13535653744 0031771 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.stringprep;
import com.ongres.saslprep.SaslPrep;
import com.ongres.scram.common.util.UsAsciiUtils;
import static com.ongres.scram.common.util.Preconditions.checkNotEmpty;
public enum StringPreparations implements StringPreparation {
/**
* Implementation of StringPreparation that performs no preparation.
* Non US-ASCII characters will produce an exception.
* Even though the [RFC5802] is not very clear about it,
* this implementation will normalize non-printable US-ASCII characters similarly to what SaslPrep does
* (i.e., removing them).
*/
NO_PREPARATION {
@Override
protected String doNormalize(String value) throws IllegalArgumentException {
return UsAsciiUtils.toPrintable(value);
}
},
/**
* Implementation of StringPreparation that performs preparation.
* Non US-ASCII characters will produce an exception.
* Even though the [RFC5802] is not very clear about it,
* this implementation will normalize as SaslPrep does.
*/
SASL_PREPARATION {
@Override
protected String doNormalize(String value) throws IllegalArgumentException {
return SaslPrep.saslPrep(value, true);
}
}
;
protected abstract String doNormalize(String value) throws IllegalArgumentException;
public String normalize(String value) throws IllegalArgumentException {
checkNotEmpty(value, "value");
String normalized = doNormalize(value);
if(null == normalized || normalized.isEmpty()) {
throw new IllegalArgumentException("null or empty value after normalization");
}
return normalized;
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/util/ 0000775 0000000 0000000 00000000000 13535653744 0024051 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/main/java/com/ongres/scram/common/util/AbstractCharAttributeValue.java 0000664 0000000 0000000 00000004733 13535653744 0032145 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
import static com.ongres.scram.common.util.Preconditions.checkNotNull;
/**
* Construct and write generic CharAttribute-Value pairs.
*
* Concrete sub-classes should also provide a static parse(String) creation method.
*/
public class AbstractCharAttributeValue extends AbstractStringWritable implements CharAttributeValue {
private final CharAttribute charAttribute;
private final String value;
public AbstractCharAttributeValue(CharAttribute charAttribute, String value) throws IllegalArgumentException {
this.charAttribute = checkNotNull(charAttribute, "attribute");
if(null != value && value.isEmpty()) {
throw new IllegalArgumentException("Value should be either null or non-empty");
}
this.value = value;
}
@Override
public char getChar() {
return charAttribute.getChar();
}
@Override
public String getValue() {
return value;
}
@Override
public StringBuffer writeTo(StringBuffer sb) {
sb.append(charAttribute.getChar());
if(null != value) {
sb.append('=').append(value);
}
return sb;
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/util/AbstractStringWritable.java 0000664 0000000 0000000 00000003141 13535653744 0031337 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
/**
* Basic implementation of the StringWritable interface, that overrides the toString() method.
*/
public abstract class AbstractStringWritable implements StringWritable {
public String toString() {
return writeTo(new StringBuffer()).toString();
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/util/CharAttribute.java 0000664 0000000 0000000 00000003126 13535653744 0027457 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
/**
* Represents an attribute (a key name) that is represented by a single char.
*/
public interface CharAttribute {
/**
* Return the char used to represent this attribute
* @return The character of the attribute
*/
char getChar();
}
scram-2.1/common/src/main/java/com/ongres/scram/common/util/CharAttributeValue.java 0000664 0000000 0000000 00000003304 13535653744 0030452 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
/**
* Augments a {@link CharAttribute} with a String value and the method(s) to write its data to a StringBuffer.
*/
public interface CharAttributeValue extends CharAttribute, StringWritable {
/**
* Returns the value associated with the {@link CharAttribute}
* @return The String value or null if no value is associated
*/
String getValue();
}
scram-2.1/common/src/main/java/com/ongres/scram/common/util/CryptoUtil.java 0000664 0000000 0000000 00000015360 13535653744 0027037 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import static com.ongres.scram.common.util.Preconditions.checkArgument;
import static com.ongres.scram.common.util.Preconditions.checkNotNull;
/**
* Utility static methods for cryptography related tasks.
*/
public class CryptoUtil {
private static final int MIN_ASCII_PRINTABLE_RANGE = 0x21;
private static final int MAX_ASCII_PRINTABLE_RANGE = 0x7e;
private static final int EXCLUDED_CHAR = (int) ','; // 0x2c
private static class SecureRandomHolder {
private static final SecureRandom INSTANCE = new SecureRandom();
}
/**
* Generates a random string (called a 'nonce'), composed of ASCII printable characters, except comma (',').
* @param size The length of the nonce, in characters/bytes
* @param random The SecureRandom to use
* @return The String representing the nonce
*/
public static String nonce(int size, SecureRandom random) {
if(size <= 0) {
throw new IllegalArgumentException("Size must be positive");
}
char[] chars = new char[size];
int r;
for(int i = 0; i < size;) {
r = random.nextInt(MAX_ASCII_PRINTABLE_RANGE - MIN_ASCII_PRINTABLE_RANGE + 1) + MIN_ASCII_PRINTABLE_RANGE;
if(r != EXCLUDED_CHAR) {
chars[i++] = (char) r;
}
}
return new String(chars);
}
/**
* Generates a random string (called a 'nonce'), composed of ASCII printable characters, except comma (',').
* It uses a default SecureRandom instance.
* @param size The length of the nonce, in characters/bytes
* @return The String representing the nonce
*/
public static String nonce(int size) {
return nonce(size, SecureRandomHolder.INSTANCE);
}
/**
* Compute the "Hi" function for SCRAM.
*
* {@code
* Hi(str, salt, i):
*
* U1 := HMAC(str, salt + INT(1))
* U2 := HMAC(str, U1)
* ...
* Ui-1 := HMAC(str, Ui-2)
* Ui := HMAC(str, Ui-1)
*
* Hi := U1 XOR U2 XOR ... XOR Ui
*
* where "i" is the iteration count, "+" is the string concatenation
* operator, and INT(g) is a 4-octet encoding of the integer g, most
* significant octet first.
*
* Hi() is, essentially, PBKDF2 [RFC2898] with HMAC() as the
* pseudorandom function (PRF) and with dkLen == output length of
* HMAC() == output length of H().
* }
*
* @param secretKeyFactory The SecretKeyFactory to generate the SecretKey
* @param keyLength The length of the key (in bits)
* @param value The char array to compute the Hi function
* @param salt The salt
* @param iterations The number of iterations
* @return The bytes of the computed Hi value
*/
public static byte[] hi(
SecretKeyFactory secretKeyFactory, int keyLength, char[] value, byte[] salt, int iterations
) {
try {
PBEKeySpec spec = new PBEKeySpec(value, salt, iterations, keyLength);
SecretKey key = secretKeyFactory.generateSecret(spec);
return key.getEncoded();
} catch(InvalidKeySpecException e) {
throw new RuntimeException("Platform error: unsupported PBEKeySpec");
}
}
/**
* Computes the HMAC of a given message.
*
* {@code
* HMAC(key, str): Apply the HMAC keyed hash algorithm (defined in
* [RFC2104]) using the octet string represented by "key" as the key
* and the octet string "str" as the input string. The size of the
* result is the hash result size for the hash function in use. For
* example, it is 20 octets for SHA-1 (see [RFC3174]).
* }
*
* @param secretKeySpec A key of the given algorithm
* @param mac A MAC instance of the given algorithm
* @param message The message to compute the HMAC
* @return The bytes of the computed HMAC value
*/
public static byte[] hmac(SecretKeySpec secretKeySpec, Mac mac, byte[] message) {
try {
mac.init(secretKeySpec);
} catch (InvalidKeyException e) {
throw new RuntimeException("Platform error: unsupported key for HMAC algorithm");
}
return mac.doFinal(message);
}
/**
* Computes a byte-by-byte xor operation.
*
* {@code
* XOR: Apply the exclusive-or operation to combine the octet string
* on the left of this operator with the octet string on the right of
* this operator. The length of the output and each of the two
* inputs will be the same for this use.
* }
*
* @param value1
* @param value2
* @return
* @throws IllegalArgumentException
*/
public static byte[] xor(byte[] value1, byte[] value2) throws IllegalArgumentException {
checkNotNull(value1, "value1");
checkNotNull(value2, "value2");
checkArgument(value1.length == value2.length, "Both values must have the same length");
byte[] result = new byte[value1.length];
for(int i = 0; i < value1.length; i++) {
result[i] = (byte) (value1[i] ^ value2[i]);
}
return result;
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/util/Preconditions.java 0000664 0000000 0000000 00000007124 13535653744 0027540 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
/**
* Simple methods similar to Precondition class. Avoid importing full library.
*/
public class Preconditions {
/**
* Checks that the argument is not null.
* @param value The value to be checked
* @param valueName The name of the value that is checked in the method
* @param The type of the value
* @return The same value passed as argument
* @throws IllegalArgumentException If value is null
*/
public static T checkNotNull(T value, String valueName) throws IllegalArgumentException {
if(null == value) {
throw new IllegalArgumentException("Null value for '" + valueName + "'");
}
return value;
}
/**
* Checks that the String is not null and not empty
* @param value The String to check
* @param valueName The name of the value that is checked in the method
* @return The same String passed as argument
* @throws IllegalArgumentException If value is null or empty
*/
public static String checkNotEmpty(String value, String valueName) throws IllegalArgumentException {
if(checkNotNull(value, valueName).isEmpty()) {
throw new IllegalArgumentException("Empty string '" + valueName + "'");
}
return value;
}
/**
* Checks that the argument is valid, based in a check boolean condition.
* @param check The boolean check
* @param valueName The name of the value that is checked in the method
* @throws IllegalArgumentException
*/
public static void checkArgument(boolean check, String valueName) throws IllegalArgumentException {
if(! check) {
throw new IllegalArgumentException("Argument '" + valueName + "' is not valid");
}
}
/**
* Checks that the integer argument is positive.
* @param value The value to be checked
* @param valueName The name of the value that is checked in the method
* @return The same value passed as argument
* @throws IllegalArgumentException If value is null
*/
public static int gt0(int value, String valueName) throws IllegalArgumentException {
if(value <= 0) {
throw new IllegalArgumentException("'" + valueName + "' must be positive");
}
return value;
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/util/StringWritable.java 0000664 0000000 0000000 00000003212 13535653744 0027652 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
/**
* Interface to denote classes which can write to a StringBuffer.
*/
public interface StringWritable {
/**
* Write the class information to the given StringBuffer.
* @param sb Where to write the data.
* @return The same StringBuffer.
*/
StringBuffer writeTo(StringBuffer sb);
}
scram-2.1/common/src/main/java/com/ongres/scram/common/util/StringWritableCsv.java 0000664 0000000 0000000 00000012275 13535653744 0030337 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
import java.util.Arrays;
import static com.ongres.scram.common.util.Preconditions.checkNotNull;
/**
* Helper class to generate Comma Separated Values of {@link StringWritable}s
*/
public class StringWritableCsv {
private static void writeStringWritableToStringBuffer(StringWritable value, StringBuffer sb) {
if(null != value) {
value.writeTo(sb);
}
}
/**
* Write a sequence of {@link StringWritableCsv}s to a StringBuffer.
* Null {@link StringWritable}s are not printed, but separator is still used.
* Separator is a comma (',')
* @param sb The sb to write to
* @param values Zero or more attribute-value pairs to write
* @return The same sb, with data filled in (if any)
* @throws IllegalArgumentException If sb is null
*/
public static StringBuffer writeTo(StringBuffer sb, StringWritable... values) throws IllegalArgumentException {
checkNotNull(sb, "sb");
if(null == values || values.length == 0) {
return sb;
}
writeStringWritableToStringBuffer(values[0], sb);
int i = 1;
while (i < values.length) {
sb.append(',');
writeStringWritableToStringBuffer(values[i], sb);
i++;
}
return sb;
}
/**
* Parse a String with a {@link StringWritableCsv} into its composing Strings
* represented as Strings. No validation is performed on the individual attribute-values returned.
* @param value The String with the set of attribute-values
* @param n Number of entries to return (entries will be null of there were not enough). 0 means unlimited
* @param offset How many entries to skip before start returning
* @return An array of Strings which represent the individual attribute-values
* @throws IllegalArgumentException If value is null or either n or offset are negative
*/
public static String[] parseFrom(String value, int n, int offset) throws IllegalArgumentException {
checkNotNull(value, "value");
if(n < 0 || offset < 0) {
throw new IllegalArgumentException("Limit and offset have to be >= 0");
}
if(value.isEmpty()) {
return new String[0];
}
String[] split = value.split(",");
if(split.length < offset) {
throw new IllegalArgumentException("Not enough items for the given offset");
}
return Arrays.copyOfRange(
split,
offset,
(n == 0 ? split.length : n) + offset
);
}
/**
* Parse a String with a {@link StringWritableCsv} into its composing Strings
* represented as Strings. No validation is performed on the individual attribute-values returned.
* Elements are returned starting from the first available attribute-value.
* @param value The String with the set of attribute-values
* @param n Number of entries to return (entries will be null of there were not enough). 0 means unlimited
* @return An array of Strings which represent the individual attribute-values
* @throws IllegalArgumentException If value is null or n is negative
*/
public static String[] parseFrom(String value, int n) throws IllegalArgumentException {
return parseFrom(value, n, 0);
}
/**
* Parse a String with a {@link StringWritableCsv} into its composing Strings
* represented as Strings. No validation is performed on the individual attribute-values returned.
* All the available attribute-values will be returned.
* @param value The String with the set of attribute-values
* @return An array of Strings which represent the individual attribute-values
* @throws IllegalArgumentException If value is null
*/
public static String[] parseFrom(String value) throws IllegalArgumentException{
return parseFrom(value, 0, 0);
}
}
scram-2.1/common/src/main/java/com/ongres/scram/common/util/UsAsciiUtils.java 0000664 0000000 0000000 00000004511 13535653744 0027276 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
import static com.ongres.scram.common.util.Preconditions.checkNotNull;
public class UsAsciiUtils {
/**
* Removes non-printable characters from the US-ASCII String.
* @param value The original String
* @return The possibly modified String, without non-printable US-ASCII characters.
* @throws IllegalArgumentException If the String is null or contains non US-ASCII characters.
*/
public static String toPrintable(String value) throws IllegalArgumentException {
checkNotNull(value, "value");
char[] printable = new char[value.length()];
int i = 0;
for(char chr : value.toCharArray()) {
int c = (int) chr;
if (c < 0 || c >= 127) {
throw new IllegalArgumentException("value contains character '" + chr + "' which is non US-ASCII");
} else if (c > 32) {
printable[i++] = chr;
}
}
return i == value.length() ? value : new String(printable, 0, i);
}
}
scram-2.1/common/src/test/ 0000775 0000000 0000000 00000000000 13535653744 0015536 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/test/java/ 0000775 0000000 0000000 00000000000 13535653744 0016457 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/test/java/com/ 0000775 0000000 0000000 00000000000 13535653744 0017235 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/test/java/com/ongres/ 0000775 0000000 0000000 00000000000 13535653744 0020532 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/test/java/com/ongres/scram/ 0000775 0000000 0000000 00000000000 13535653744 0021637 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/test/java/com/ongres/scram/common/ 0000775 0000000 0000000 00000000000 13535653744 0023127 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/test/java/com/ongres/scram/common/RfcExampleSha1.java 0000664 0000000 0000000 00000005456 13535653744 0026547 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common;
public class RfcExampleSha1 {
public static final String USER = "user";
public static final String PASSWORD = "pencil";
public static final String CLIENT_NONCE = "fyko+d2lbbFgONRv9qkxdawL";
public static final String CLIENT_FIRST_MESSAGE_WITHOUT_GS2_HEADER = "n=" + USER + ",r=" + CLIENT_NONCE;
public static final String CLIENT_FIRST_MESSAGE = "n," + "," + CLIENT_FIRST_MESSAGE_WITHOUT_GS2_HEADER;
public static final String SERVER_SALT = "QSXCR+Q6sek8bf92";
public static final int SERVER_ITERATIONS = 4096;
public static final String SERVER_NONCE = "3rfcNHYJY1ZVvWVs7j";
public static final String FULL_NONCE = CLIENT_NONCE + SERVER_NONCE;
public static final String SERVER_FIRST_MESSAGE = "r=" + FULL_NONCE + ",s=" + SERVER_SALT
+ ",i=" + SERVER_ITERATIONS;
public static final String GS2_HEADER_BASE64 = "biws";
public static final String CLIENT_FINAL_MESSAGE_WITHOUT_PROOF = "c=" + GS2_HEADER_BASE64
+ ",r=" + FULL_NONCE;
public static final String AUTH_MESSAGE = CLIENT_FIRST_MESSAGE_WITHOUT_GS2_HEADER + ","
+ SERVER_FIRST_MESSAGE + ","
+ CLIENT_FINAL_MESSAGE_WITHOUT_PROOF;
public static final String CLIENT_FINAL_MESSAGE_PROOF = "v0X8v3Bz2T0CJGbJQyF0X+HI4Ts=";
public static final String CLIENT_FINAL_MESSAGE = CLIENT_FINAL_MESSAGE_WITHOUT_PROOF
+ ",p=" + CLIENT_FINAL_MESSAGE_PROOF;
public static final String SERVER_FINAL_MESSAGE = "v=rmF9pqV8S7suAoZWja4dJRkFsKQ=";
}
scram-2.1/common/src/test/java/com/ongres/scram/common/RfcExampleSha256.java 0000664 0000000 0000000 00000005540 13535653744 0026715 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common;
public class RfcExampleSha256 {
public static final String USER = "user";
public static final String PASSWORD = "pencil";
public static final String CLIENT_NONCE = "rOprNGfwEbeRWgbNEkqO";
public static final String CLIENT_FIRST_MESSAGE_WITHOUT_GS2_HEADER = "n=" + USER + ",r=" + CLIENT_NONCE;
public static final String CLIENT_FIRST_MESSAGE = "n," + "," + CLIENT_FIRST_MESSAGE_WITHOUT_GS2_HEADER;
public static final String SERVER_SALT = "W22ZaJ0SNY7soEsUEjb6gQ==";
public static final int SERVER_ITERATIONS = 4096;
public static final String SERVER_NONCE = "%hvYDpWUa2RaTCAfuxFIlj)hNlF$k0";
public static final String FULL_NONCE = CLIENT_NONCE + SERVER_NONCE;
public static final String SERVER_FIRST_MESSAGE = "r=" + FULL_NONCE + ",s=" + SERVER_SALT
+ ",i=" + SERVER_ITERATIONS;
public static final String GS2_HEADER_BASE64 = "biws";
public static final String CLIENT_FINAL_MESSAGE_WITHOUT_PROOF = "c=" + GS2_HEADER_BASE64
+ ",r=" + FULL_NONCE;
public static final String AUTH_MESSAGE = CLIENT_FIRST_MESSAGE_WITHOUT_GS2_HEADER + ","
+ SERVER_FIRST_MESSAGE + ","
+ CLIENT_FINAL_MESSAGE_WITHOUT_PROOF;
public static final String CLIENT_FINAL_MESSAGE_PROOF = "dHzbZapWIk4jUhN+Ute9ytag9zjfMHgsqmmiz7AndVQ=";
public static final String CLIENT_FINAL_MESSAGE = CLIENT_FINAL_MESSAGE_WITHOUT_PROOF
+ ",p=" + CLIENT_FINAL_MESSAGE_PROOF;
public static final String SERVER_FINAL_MESSAGE = "v=6rriTRBi23WpRR/wtup+mMhUZUn/dB5nLTJRsjl95G4=";
}
scram-2.1/common/src/test/java/com/ongres/scram/common/ScramAttributeValueTest.java 0000664 0000000 0000000 00000010035 13535653744 0030557 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common;
import com.ongres.scram.common.exception.ScramParseException;
import com.ongres.scram.common.message.ServerFinalMessage;
import org.junit.Test;
import static com.ongres.scram.common.RfcExampleSha1.*;
import static com.ongres.scram.common.ScramAttributes.CLIENT_PROOF;
import static com.ongres.scram.common.ScramAttributes.USERNAME;
import static org.junit.Assert.*;
public class ScramAttributeValueTest {
@Test
public void constructorDoesNotAllowNullValue() {
try {
assertNotNull(new ScramAttributeValue(USERNAME, null));
} catch(IllegalArgumentException e) {
return;
}
fail("A null value must throw an IllegalArgumentException");
}
@Test
public void parseIllegalValuesStructure() {
String[] values = new String[] {
null, "", "asdf", "asdf=a", CLIENT_PROOF.getChar() + "=", CLIENT_PROOF.getChar() + ",a"
};
int n = 0;
for(String value : values) {
try {
assertNotNull(ScramAttributeValue.parse(value));
} catch(ScramParseException e) {
n++;
}
}
assertEquals("Not every illegal value thrown ScramParseException", values.length, n);
}
@Test
public void parseIllegalValuesInvalidSCRAMAttibute() {
// SCRAM allows for extensions. If a new attribute is supported and its value has been used below,
// test will fail and will need to be fixed
String[] values = new String[] { "z=asdfasdf", "!=value" };
int n = 0;
for(String value : values) {
try {
assertNotNull(ScramAttributeValue.parse(value));
} catch(ScramParseException e) {
n++;
}
}
assertEquals("Not every illegal value thrown ScramParseException", values.length, n);
}
@Test
public void parseLegalValues() throws ScramParseException {
String[] legalValues = new String[] {
CLIENT_PROOF.getChar() + "=" + "proof",
USERNAME.getChar() + "=" + "username",
"n=" + USER,
"r=" + CLIENT_NONCE,
"r=" + FULL_NONCE,
"s=" + SERVER_SALT,
"i=" + SERVER_ITERATIONS,
"c=" + GS2_HEADER_BASE64,
"p=" + CLIENT_FINAL_MESSAGE_PROOF,
SERVER_FINAL_MESSAGE,
};
for(String value : legalValues) {
assertNotNull(ScramAttributeValue.parse(value));
}
// Test all possible error messages
for(ServerFinalMessage.Error e : ServerFinalMessage.Error.values()) {
assertNotNull(ScramAttributeValue.parse("e=" + e.getErrorMessage()));
}
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/ScramFunctionsTest.java 0000664 0000000 0000000 00000023727 13535653744 0027603 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common;
import com.ongres.scram.common.bouncycastle.base64.Base64;
import com.ongres.scram.common.stringprep.StringPreparations;
import org.junit.Test;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class ScramFunctionsTest {
private void assertBytesEqualsBase64(String expected, byte[] actual) {
assertArrayEquals(Base64.decode(expected), actual);
}
@Test
public void hmac() throws UnsupportedEncodingException {
String message = "The quick brown fox jumps over the lazy dog";
byte[] key = "key".getBytes(StandardCharsets.UTF_8);
assertBytesEqualsBase64(
"3nybhbi3iqa8ino29wqQcBydtNk=",
ScramFunctions.hmac(ScramMechanisms.SCRAM_SHA_1, message.getBytes(StandardCharsets.US_ASCII), key)
);
assertBytesEqualsBase64(
"97yD9DBThCSxMpjmqm+xQ+9NWaFJRhdZl0edvC0aPNg=",
ScramFunctions.hmac(ScramMechanisms.SCRAM_SHA_256, message.getBytes(StandardCharsets.US_ASCII), key)
);
}
private byte[] generateSaltedPassword() {
return ScramFunctions.saltedPassword(
ScramMechanisms.SCRAM_SHA_1, StringPreparations.NO_PREPARATION, "pencil",
Base64.decode("QSXCR+Q6sek8bf92"), 4096
);
}
private byte[] generateSaltedPasswordSha256() {
return ScramFunctions.saltedPassword(
ScramMechanisms.SCRAM_SHA_256, StringPreparations.NO_PREPARATION, "pencil",
Base64.decode("W22ZaJ0SNY7soEsUEjb6gQ=="), 4096
);
}
@Test
public void saltedPassword() {
assertBytesEqualsBase64("HZbuOlKbWl+eR8AfIposuKbhX30=", generateSaltedPassword());
}
@Test
public void saltedPasswordWithSaslPrep() {
assertBytesEqualsBase64("YniLes+b8WFMvBhtSACZyyvxeCc=", ScramFunctions.saltedPassword(
ScramMechanisms.SCRAM_SHA_1, StringPreparations.SASL_PREPARATION, "\u2168\u3000a\u0300",
Base64.decode("0BojBCBE6P2/N4bQ"), 6400
));
assertBytesEqualsBase64("YniLes+b8WFMvBhtSACZyyvxeCc=", ScramFunctions.saltedPassword(
ScramMechanisms.SCRAM_SHA_1, StringPreparations.SASL_PREPARATION, "\u00ADIX \u00E0",
Base64.decode("0BojBCBE6P2/N4bQ"), 6400
));
assertBytesEqualsBase64("YniLes+b8WFMvBhtSACZyyvxeCc=", ScramFunctions.saltedPassword(
ScramMechanisms.SCRAM_SHA_1, StringPreparations.SASL_PREPARATION, "IX \u00E0",
Base64.decode("0BojBCBE6P2/N4bQ"), 6400
));
assertBytesEqualsBase64("HZbuOlKbWl+eR8AfIposuKbhX30=", ScramFunctions.saltedPassword(
ScramMechanisms.SCRAM_SHA_1, StringPreparations.SASL_PREPARATION, "\u0070enc\u1806il",
Base64.decode("QSXCR+Q6sek8bf92"), 4096
));
try {
ScramFunctions.saltedPassword(
ScramMechanisms.SCRAM_SHA_1, StringPreparations.SASL_PREPARATION, "\u2168\u3000a\u0300\u0007",
Base64.decode("QSXCR+Q6sek8bf92"), 6400);
fail();
} catch (IllegalArgumentException e) {
assertEquals("Prohibited character \u0007", e.getMessage());
}
}
@Test
public void saltedPasswordSha256() {
assertBytesEqualsBase64("xKSVEDI6tPlSysH6mUQZOeeOp01r6B3fcJbodRPcYV0=", generateSaltedPasswordSha256());
}
private byte[] generateClientKey() {
return ScramFunctions.clientKey(ScramMechanisms.SCRAM_SHA_1, generateSaltedPassword());
}
private byte[] generateClientKeySha256() {
return ScramFunctions.clientKey(ScramMechanisms.SCRAM_SHA_256, generateSaltedPasswordSha256());
}
@Test
public void clientKey() {
assertBytesEqualsBase64("4jTEe/bDZpbdbYUrmaqiuiZVVyg=", generateClientKey());
}
@Test
public void clientKeySha256() {
assertBytesEqualsBase64("pg/JI9Z+hkSpLRa5btpe9GVrDHJcSEN0viVTVXaZbos=", generateClientKeySha256());
}
private byte[] generateStoredKey() {
return ScramFunctions.storedKey(ScramMechanisms.SCRAM_SHA_1, generateClientKey());
}
private byte[] generateStoredKeySha256() {
return ScramFunctions.storedKey(ScramMechanisms.SCRAM_SHA_256, generateClientKeySha256());
}
@Test
public void storedKey() {
assertBytesEqualsBase64("6dlGYMOdZcOPutkcNY8U2g7vK9Y=", generateStoredKey());
}
@Test
public void storedKeySha256() {
assertBytesEqualsBase64("WG5d8oPm3OtcPnkdi4Uo7BkeZkBFzpcXkuLmtbsT4qY=", generateStoredKeySha256());
}
private byte[] generateServerKey() {
return ScramFunctions.serverKey(ScramMechanisms.SCRAM_SHA_1, generateSaltedPassword());
}
private byte[] generateServerKeySha256() {
return ScramFunctions.serverKey(ScramMechanisms.SCRAM_SHA_256, generateSaltedPasswordSha256());
}
@Test
public void serverKey() {
assertBytesEqualsBase64("D+CSWLOshSulAsxiupA+qs2/fTE=", generateServerKey());
}
@Test
public void serverKeySha256() {
assertBytesEqualsBase64("wfPLwcE6nTWhTAmQ7tl2KeoiWGPlZqQxSrmfPwDl2dU=", generateServerKeySha256());
}
private byte[] generateClientSignature() {
return ScramFunctions.clientSignature(ScramMechanisms.SCRAM_SHA_1, generateStoredKey(), com.ongres.scram.common.RfcExampleSha1.AUTH_MESSAGE);
}
private byte[] generateClientSignatureSha256() {
return ScramFunctions.clientSignature(ScramMechanisms.SCRAM_SHA_256, generateStoredKeySha256(), com.ongres.scram.common.RfcExampleSha256.AUTH_MESSAGE);
}
@Test
public void clientSignature() {
assertBytesEqualsBase64("XXE4xIawv6vfSePi2ovW5cedthM=", generateClientSignature());
}
@Test
public void clientSignatureSha256() {
assertBytesEqualsBase64("0nMSRnwopAqKfwXHPA3jPrPL+0qDeDtYFEzxmsa+G98=", generateClientSignatureSha256());
}
private byte[] generateClientProof() {
return ScramFunctions.clientProof(generateClientKey(), generateClientSignature());
}
private byte[] generateClientProofSha256() {
return ScramFunctions.clientProof(generateClientKeySha256(), generateClientSignatureSha256());
}
@Test
public void clientProof() {
assertBytesEqualsBase64("v0X8v3Bz2T0CJGbJQyF0X+HI4Ts=", generateClientProof());
}
@Test
public void clientProofSha256() {
assertBytesEqualsBase64("dHzbZapWIk4jUhN+Ute9ytag9zjfMHgsqmmiz7AndVQ=", generateClientProofSha256());
}
private byte[] generateServerSignature() {
return ScramFunctions.serverSignature(ScramMechanisms.SCRAM_SHA_1, generateServerKey(), com.ongres.scram.common.RfcExampleSha1.AUTH_MESSAGE);
}
private byte[] generateServerSignatureSha256() {
return ScramFunctions.serverSignature(ScramMechanisms.SCRAM_SHA_256, generateServerKeySha256(), com.ongres.scram.common.RfcExampleSha256.AUTH_MESSAGE);
}
@Test
public void serverSignature() {
assertBytesEqualsBase64("rmF9pqV8S7suAoZWja4dJRkFsKQ=", generateServerSignature());
}
@Test
public void serverSignatureSha256() {
assertBytesEqualsBase64("6rriTRBi23WpRR/wtup+mMhUZUn/dB5nLTJRsjl95G4=", generateServerSignatureSha256());
}
@Test
public void verifyClientProof() {
assertTrue(
ScramFunctions.verifyClientProof(
ScramMechanisms.SCRAM_SHA_1, generateClientProof(), generateStoredKey(), com.ongres.scram.common.RfcExampleSha1.AUTH_MESSAGE
)
);
}
@Test
public void verifyClientProofSha256() {
assertTrue(
ScramFunctions.verifyClientProof(
ScramMechanisms.SCRAM_SHA_256, generateClientProofSha256(), generateStoredKeySha256(), com.ongres.scram.common.RfcExampleSha256.AUTH_MESSAGE
)
);
}
@Test
public void verifyServerSignature() {
assertTrue(
ScramFunctions.verifyServerSignature(
ScramMechanisms.SCRAM_SHA_1, generateServerKey(), com.ongres.scram.common.RfcExampleSha1.AUTH_MESSAGE, generateServerSignature()
)
);
}
@Test
public void verifyServerSignatureSha256() {
assertTrue(
ScramFunctions.verifyServerSignature(
ScramMechanisms.SCRAM_SHA_256, generateServerKeySha256(), com.ongres.scram.common.RfcExampleSha256.AUTH_MESSAGE, generateServerSignatureSha256()
)
);
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/ScramMechanismsTest.java 0000664 0000000 0000000 00000011234 13535653744 0027710 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
public class ScramMechanismsTest {
@Test
public void TestHashSupportedByJVM() {
byte[] digest;
for(ScramMechanisms scramMechanism : ScramMechanisms.values()) {
digest = scramMechanism.digest(new byte[0]);
assertNotNull("got a null digest", digest);
}
}
@Test
public void TestHMACSupportedByJVM() {
byte[] hmac;
for(ScramMechanisms scramMechanism : ScramMechanisms.values()) {
hmac = scramMechanism.hmac(new byte[] { 0 }, new byte[0]);
assertNotNull("got a null HMAC", hmac);
}
}
private interface Predicate {
boolean test(T t);
}
private void testNames(String[] names, Predicate predicate) {
int count = 0;
for (String name : names) {
if (predicate.test(ScramMechanisms.byName(name))) {
count++;
}
}
assertEquals(
names.length,
count
);
}
@Test
public void byNameValid() {
testNames(
new String[] { "SCRAM-SHA-1", "SCRAM-SHA-1-PLUS", "SCRAM-SHA-256", "SCRAM-SHA-256-PLUS" },
new Predicate() {
@Override
public boolean test(ScramMechanisms scramMechanisms) {
return scramMechanisms != null;
}
}
);
}
@Test
public void byNameInvalid() {
testNames(
new String[] { "SCRAM-SHA", "SHA-1-PLUS", "SCRAM-SHA-256-", "SCRAM-SHA-256-PLUS!" },
new Predicate() {
@Override
public boolean test(ScramMechanisms scramMechanisms) {
return scramMechanisms == null;
}
}
);
}
private void selectMatchingMechanismTest(ScramMechanisms scramMechanisms, boolean channelBinding, String... names) {
assertEquals(
scramMechanisms, ScramMechanisms.selectMatchingMechanism(channelBinding, names)
);
}
@Test
public void selectMatchingMechanism() {
selectMatchingMechanismTest(
ScramMechanisms.SCRAM_SHA_1, false,
"SCRAM-SHA-1"
);
selectMatchingMechanismTest(
ScramMechanisms.SCRAM_SHA_256_PLUS, true,
"SCRAM-SHA-256-PLUS"
);
selectMatchingMechanismTest(
ScramMechanisms.SCRAM_SHA_256, false,
"SCRAM-SHA-1", "SCRAM-SHA-256"
);
selectMatchingMechanismTest(
ScramMechanisms.SCRAM_SHA_256, false,
"SCRAM-SHA-1", "SCRAM-SHA-256", "SCRAM-SHA-256-PLUS"
);
selectMatchingMechanismTest(
ScramMechanisms.SCRAM_SHA_1_PLUS, true,
"SCRAM-SHA-1", "SCRAM-SHA-1-PLUS", "SCRAM-SHA-256"
);
selectMatchingMechanismTest(
ScramMechanisms.SCRAM_SHA_256_PLUS, true,
"SCRAM-SHA-1", "SCRAM-SHA-1-PLUS", "SCRAM-SHA-256", "SCRAM-SHA-256-PLUS"
);
selectMatchingMechanismTest(
null, true,
"SCRAM-SHA-1", "SCRAM-SHA-256"
);
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/ScramStringFormattingTest.java 0000664 0000000 0000000 00000006542 13535653744 0031130 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class ScramStringFormattingTest {
private static final String[] VALUES_NO_CHARS_TO_BE_ESCAPED = new String[] { "asdf", "''--%%21", " ttt???" };
private static final String[] VALUES_TO_BE_ESCAPED = new String[] {
",", "=", "a,b", "===", "a=", ",=,", "=2C", "=3D"
};
private static final String[] ESCAPED_VALUES = new String[] {
"=2C", "=3D", "a=2Cb", "=3D=3D=3D", "a=3D", "=2C=3D=2C", "=3D2C", "=3D3D"
};
private static final String[] INVALID_SASL_NAMES = new String[] { "=", "as,df", "a=b", " ttt???=2D" };
@Test
public void toSaslNameNoCharactersToBeEscaped() {
for(String s : VALUES_NO_CHARS_TO_BE_ESCAPED) {
assertEquals(s, ScramStringFormatting.toSaslName(s));
}
}
@Test
public void toSaslNameWithCharactersToBeEscaped() {
for(int i = 0; i < VALUES_TO_BE_ESCAPED.length; i++) {
assertEquals(ESCAPED_VALUES[i], ScramStringFormatting.toSaslName(VALUES_TO_BE_ESCAPED[i]));
}
}
@Test
public void fromSaslNameNoCharactersToBeEscaped() {
for(String s : VALUES_NO_CHARS_TO_BE_ESCAPED) {
assertEquals(s, ScramStringFormatting.fromSaslName(s));
}
}
@Test
public void fromSaslNameWithCharactersToBeUnescaped() {
for(int i = 0; i < ESCAPED_VALUES.length; i++) {
assertEquals(VALUES_TO_BE_ESCAPED[i], ScramStringFormatting.fromSaslName(ESCAPED_VALUES[i]));
}
}
@Test
public void fromSaslNameWithInvalidCharacters() {
int n = 0;
for(String s : INVALID_SASL_NAMES) {
try {
assertEquals(s, ScramStringFormatting.fromSaslName(s));
} catch (IllegalArgumentException e) {
n++;
}
}
assertTrue("Not all values produced IllegalArgumentException", n == INVALID_SASL_NAMES.length);
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/gssapi/ 0000775 0000000 0000000 00000000000 13535653744 0024415 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/test/java/com/ongres/scram/common/gssapi/Gs2AttributeValueTest.java 0000664 0000000 0000000 00000006052 13535653744 0031437 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.gssapi;
import org.junit.Test;
import static org.junit.Assert.*;
public class Gs2AttributeValueTest {
@Test
public void constructorAllowsNullValue() {
try {
assertNotNull(new Gs2AttributeValue(Gs2Attributes.CHANNEL_BINDING_REQUIRED, null));
} catch(IllegalArgumentException e) {
fail("A null value is valid and cannot throw an IllegalArgumentException");
}
}
@Test
public void parseNullValue() {
assertNull(Gs2AttributeValue.parse(null));
}
@Test
public void parseIllegalValuesStructure() {
String[] values = new String[] { "", "as", "asdfjkl", Gs2Attributes.CHANNEL_BINDING_REQUIRED.getChar() + "=" };
int n = 0;
for(String value : values) {
try {
assertNotNull(Gs2AttributeValue.parse(value));
} catch(IllegalArgumentException e) {
n++;
}
}
assertEquals("Not every illegal value thrown IllegalArgumentException", values.length, n);
}
@Test
public void parseIllegalValuesInvalidGS2Attibute() {
String[] values = new String[] { "z=asdfasdf", "i=value" };
int n = 0;
for(String value : values) {
try {
assertNotNull(Gs2AttributeValue.parse(value));
} catch(IllegalArgumentException e) {
n++;
}
}
assertEquals("Not every illegal value thrown IllegalArgumentException", values.length, n);
}
@Test
public void parseLegalValues() {
String[] values = new String[] { "n", "y", "p=value", "a=authzid" };
for(String value : values) {
assertNotNull(Gs2AttributeValue.parse(value));
}
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/gssapi/Gs2HeaderTest.java 0000664 0000000 0000000 00000007346 13535653744 0027676 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.gssapi;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class Gs2HeaderTest {
private static final String[] VALID_GS2HEADER_STRINGS = new String[] {
"n,", "y,", "n,a=blah", "p=cb,", "p=cb,a=b"
};
private static final Gs2Header[] VALID_GS_2_HEADERS = new Gs2Header[] {
new Gs2Header(Gs2CbindFlag.CLIENT_NOT),
new Gs2Header(Gs2CbindFlag.CLIENT_YES_SERVER_NOT),
new Gs2Header(Gs2CbindFlag.CLIENT_NOT, null, "blah"),
new Gs2Header(Gs2CbindFlag.CHANNEL_BINDING_REQUIRED, "cb"),
new Gs2Header(Gs2CbindFlag.CHANNEL_BINDING_REQUIRED, "cb", "b")
};
private void assertGS2Header(String expected, Gs2Header gs2Header) {
assertEquals(expected, gs2Header.writeTo(new StringBuffer()).toString());
}
@Test
public void constructorValid() {
for(int i = 0; i < VALID_GS2HEADER_STRINGS.length; i++) {
assertGS2Header(VALID_GS2HEADER_STRINGS[i], VALID_GS_2_HEADERS[i]);
}
}
@Test(expected = IllegalArgumentException.class)
public void constructorInvalid1() {
new Gs2Header(Gs2CbindFlag.CHANNEL_BINDING_REQUIRED, null);
}
@Test(expected = IllegalArgumentException.class)
public void constructorInvalid2() {
new Gs2Header(Gs2CbindFlag.CLIENT_NOT, "blah");
}
@Test(expected = IllegalArgumentException.class)
public void constructorInvalid3() {
new Gs2Header(Gs2CbindFlag.CLIENT_YES_SERVER_NOT, "blah");
}
@Test(expected = IllegalArgumentException.class)
public void constructorInvalid4() {
new Gs2Header(Gs2CbindFlag.CHANNEL_BINDING_REQUIRED, null, "b");
}
@Test
public void parseFromInvalid() {
String[] invalids = new String[] { "Z,", "n,Z=blah", "p,", "n=a," };
int n = 0;
for(String invalid : invalids) {
try {
Gs2Header.parseFrom(invalid);
System.out.println(invalid);
} catch (IllegalArgumentException e) {
n++;
}
}
assertEquals(invalids.length, n);
}
@Test
public void parseFromValid() {
for(int i = 0; i < VALID_GS2HEADER_STRINGS.length; i++) {
assertGS2Header(
VALID_GS_2_HEADERS[i].writeTo(new StringBuffer()).toString(),
Gs2Header.parseFrom(VALID_GS2HEADER_STRINGS[i])
);
}
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/message/ 0000775 0000000 0000000 00000000000 13535653744 0024553 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/test/java/com/ongres/scram/common/message/ClientFinalMessageTest.java 0000664 0000000 0000000 00000003624 13535653744 0031760 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.message;
import com.ongres.scram.common.RfcExampleSha1;
import com.ongres.scram.common.gssapi.Gs2CbindFlag;
import com.ongres.scram.common.gssapi.Gs2Header;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ClientFinalMessageTest {
@Test
public void writeToWithoutProofValid() {
StringBuffer sb = ClientFinalMessage.writeToWithoutProof(
new Gs2Header(Gs2CbindFlag.CLIENT_NOT), null, RfcExampleSha1.FULL_NONCE
);
assertEquals(RfcExampleSha1.CLIENT_FINAL_MESSAGE_WITHOUT_PROOF, sb.toString());
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/message/ClientFirstMessageTest.java 0000664 0000000 0000000 00000013633 13535653744 0032017 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.message;
import com.ongres.scram.common.exception.ScramParseException;
import com.ongres.scram.common.gssapi.Gs2CbindFlag;
import org.junit.Test;
import static com.ongres.scram.common.RfcExampleSha1.CLIENT_NONCE;
import static org.junit.Assert.*;
public class ClientFirstMessageTest {
@Test(expected = IllegalArgumentException.class)
public void constructorTestInvalid1() {
assertNotNull(new ClientFirstMessage(null, "a", CLIENT_NONCE));
}
@Test(expected = IllegalArgumentException.class)
public void constructorTestInvalid2() {
assertNotNull(
new ClientFirstMessage(Gs2CbindFlag.CLIENT_NOT, null, "cbind", "a", CLIENT_NONCE)
);
}
@Test(expected = IllegalArgumentException.class)
public void constructorTestInvalid3() {
assertNotNull(
new ClientFirstMessage(Gs2CbindFlag.CLIENT_YES_SERVER_NOT, null, "cbind", "a", CLIENT_NONCE)
);
}
@Test(expected = IllegalArgumentException.class)
public void constructorTestInvalid4() {
assertNotNull(new ClientFirstMessage(Gs2CbindFlag.CHANNEL_BINDING_REQUIRED, null, null, "a", CLIENT_NONCE));
}
@Test(expected = IllegalArgumentException.class)
public void constructorTestInvalid5() {
assertNotNull(new ClientFirstMessage(Gs2CbindFlag.CLIENT_NOT, "authzid", null, null, CLIENT_NONCE));
}
private void assertClientFirstMessage(String expected, ClientFirstMessage clientFirstMessage) {
assertEquals(expected, clientFirstMessage.writeTo(new StringBuffer()).toString());
}
@Test
public void writeToValidValues() {
assertClientFirstMessage(
"n,,n=user,r=" + CLIENT_NONCE,
new ClientFirstMessage("user", CLIENT_NONCE)
);
assertClientFirstMessage(
"y,,n=user,r=" + CLIENT_NONCE,
new ClientFirstMessage(Gs2CbindFlag.CLIENT_YES_SERVER_NOT, null, null, "user", CLIENT_NONCE)
);
assertClientFirstMessage(
"p=blah,,n=user,r=" + CLIENT_NONCE,
new ClientFirstMessage(Gs2CbindFlag.CHANNEL_BINDING_REQUIRED, null, "blah", "user", CLIENT_NONCE)
);
assertClientFirstMessage(
"p=blah,a=authzid,n=user,r=" + CLIENT_NONCE,
new ClientFirstMessage(Gs2CbindFlag.CHANNEL_BINDING_REQUIRED, "authzid", "blah", "user", CLIENT_NONCE)
);
}
@Test
public void parseFromValidValues() throws ScramParseException {
ClientFirstMessage m1 = ClientFirstMessage.parseFrom("n,,n=user,r=" + CLIENT_NONCE);
assertTrue(
! m1.isChannelBinding() && m1.getChannelBindingFlag() == Gs2CbindFlag.CLIENT_NOT
&& null == m1.getAuthzid() && "user".equals(m1.getUser()) && CLIENT_NONCE.equals(m1.getNonce())
);
ClientFirstMessage m2 = ClientFirstMessage.parseFrom("y,,n=user,r=" + CLIENT_NONCE);
assertTrue(
! m2.isChannelBinding() && m2.getChannelBindingFlag() == Gs2CbindFlag.CLIENT_YES_SERVER_NOT
&& null == m2.getAuthzid() && "user".equals(m2.getUser()) && CLIENT_NONCE.equals(m2.getNonce())
);
ClientFirstMessage m3 = ClientFirstMessage.parseFrom("y,a=user2,n=user,r=" + CLIENT_NONCE);
assertTrue(
! m3.isChannelBinding() && m3.getChannelBindingFlag() == Gs2CbindFlag.CLIENT_YES_SERVER_NOT
&& null != m3.getAuthzid() && "user2".equals(m3.getAuthzid())
&& "user".equals(m3.getUser()) && CLIENT_NONCE.equals(m3.getNonce())
);
ClientFirstMessage m4 = ClientFirstMessage.parseFrom("p=channel,a=user2,n=user,r=" + CLIENT_NONCE);
assertTrue(
m4.isChannelBinding() && m4.getChannelBindingFlag() == Gs2CbindFlag.CHANNEL_BINDING_REQUIRED
&& null != m4.getChannelBindingName() && "channel".equals(m4.getChannelBindingName())
&& null != m4.getAuthzid() && "user2".equals(m4.getAuthzid())
&& "user".equals(m4.getUser()) && CLIENT_NONCE.equals(m4.getNonce())
);
}
@Test
public void parseFromInvalidValues() {
String[] invalidValues = new String[] {
"n,,r=user,r=" + CLIENT_NONCE, "n,,z=user,r=" + CLIENT_NONCE, "n,,n=user", "n,", "n,,", "n,,n=user,r", "n,,n=user,r="
};
int n = 0;
for(String s : invalidValues) {
try {
assertNotNull(ClientFirstMessage.parseFrom(s));
} catch (ScramParseException e) {
n++;
}
}
assertEquals(invalidValues.length, n);
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/message/ServerFinalMessageTest.java 0000664 0000000 0000000 00000006713 13535653744 0032012 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.message;
import com.ongres.scram.common.ScramAttributes;
import com.ongres.scram.common.ScramFunctions;
import com.ongres.scram.common.ScramMechanisms;
import com.ongres.scram.common.bouncycastle.base64.Base64;
import com.ongres.scram.common.exception.ScramParseException;
import com.ongres.scram.common.stringprep.StringPreparations;
import org.junit.Test;
import static com.ongres.scram.common.RfcExampleSha1.*;
import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class ServerFinalMessageTest {
@Test
public void validConstructor() {
byte[] serverKey = ScramFunctions.serverKey(
ScramMechanisms.SCRAM_SHA_1,
StringPreparations.NO_PREPARATION,
PASSWORD,
Base64.decode(SERVER_SALT),
SERVER_ITERATIONS
);
ServerFinalMessage serverFinalMessage1 = new ServerFinalMessage(
ScramFunctions.serverSignature(ScramMechanisms.SCRAM_SHA_1, serverKey, AUTH_MESSAGE)
);
assertEquals(SERVER_FINAL_MESSAGE, serverFinalMessage1.toString());
assertFalse(serverFinalMessage1.isError());
ServerFinalMessage serverFinalMessage2 = new ServerFinalMessage(ServerFinalMessage.Error.UNKNOWN_USER);
assertEquals(ScramAttributes.ERROR.getChar() + "=" + "unknown-user", serverFinalMessage2.toString());
assertTrue(serverFinalMessage2.isError());
}
@Test
public void validParseFrom() throws ScramParseException {
ServerFinalMessage serverFinalMessage1 = ServerFinalMessage.parseFrom(SERVER_FINAL_MESSAGE);
assertEquals(SERVER_FINAL_MESSAGE, serverFinalMessage1.toString());
assertFalse(serverFinalMessage1.isError());
ServerFinalMessage serverFinalMessage2 = ServerFinalMessage.parseFrom("e=channel-binding-not-supported");
assertEquals("e=channel-binding-not-supported", serverFinalMessage2.toString());
assertTrue(serverFinalMessage2.isError());
assertTrue(serverFinalMessage2.getError() == ServerFinalMessage.Error.CHANNEL_BINDING_NOT_SUPPORTED);
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/message/ServerFirstMessageTest.java 0000664 0000000 0000000 00000004357 13535653744 0032052 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.message;
import com.ongres.scram.common.exception.ScramParseException;
import org.junit.Test;
import static com.ongres.scram.common.RfcExampleSha1.CLIENT_NONCE;
import static com.ongres.scram.common.RfcExampleSha1.SERVER_FIRST_MESSAGE;
import static org.junit.Assert.assertEquals;
public class ServerFirstMessageTest {
@Test
public void validConstructor() {
ServerFirstMessage serverFirstMessage = new ServerFirstMessage(
CLIENT_NONCE,
"3rfcNHYJY1ZVvWVs7j",
"QSXCR+Q6sek8bf92",
4096
);
assertEquals(SERVER_FIRST_MESSAGE, serverFirstMessage.toString());
}
@Test
public void validParseFrom() throws ScramParseException {
ServerFirstMessage serverFirstMessage = ServerFirstMessage.parseFrom(SERVER_FIRST_MESSAGE, CLIENT_NONCE);
assertEquals(SERVER_FIRST_MESSAGE, serverFirstMessage.toString());
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/stringprep/ 0000775 0000000 0000000 00000000000 13535653744 0025324 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/test/java/com/ongres/scram/common/stringprep/SaslPrepTest.java 0000664 0000000 0000000 00000010532 13535653744 0030561 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.stringprep;
import com.ongres.saslprep.SaslPrep;
import com.ongres.stringprep.StringPrep;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;
public class SaslPrepTest {
@Test
public void rfc4013Examples() throws IOException {
// Taken from https://tools.ietf.org/html/rfc4013#section-3
Assert.assertEquals("IX", SaslPrep.saslPrep("I\u00ADX", true));
Assert.assertEquals("user", SaslPrep.saslPrep("user", true));
Assert.assertEquals("USER", SaslPrep.saslPrep("USER", true));
Assert.assertEquals("a", SaslPrep.saslPrep("\u00AA", true));
Assert.assertEquals("IX", SaslPrep.saslPrep("\u2168", true));
try {
SaslPrep.saslPrep("\u0007", true);
Assert.fail("Should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
Assert.assertEquals("Prohibited character ", e.getMessage());
}
try {
SaslPrep.saslPrep("\u0627\u0031", true);
Assert.fail("Should thow IllegalArgumentException");
} catch (IllegalArgumentException e) {
Assert.assertEquals("The string contains any RandALCat character but a RandALCat character "
+ "is not the first and the last characters", e.getMessage());
}
}
@Test
public void unassigned() throws IOException {
int unassignedCodepoint;
for (unassignedCodepoint = Character.MAX_CODE_POINT;
unassignedCodepoint >= Character.MIN_CODE_POINT;
unassignedCodepoint--) {
if (!Character.isDefined(unassignedCodepoint) &&
!StringPrep.prohibitionAsciiControl(unassignedCodepoint) &&
!StringPrep.prohibitionAsciiSpace(unassignedCodepoint) &&
!StringPrep.prohibitionChangeDisplayProperties(unassignedCodepoint) &&
!StringPrep.prohibitionInappropriateCanonicalRepresentation(unassignedCodepoint) &&
!StringPrep.prohibitionInappropriatePlainText(unassignedCodepoint) &&
!StringPrep.prohibitionNonAsciiControl(unassignedCodepoint) &&
!StringPrep.prohibitionNonAsciiSpace(unassignedCodepoint) &&
!StringPrep.prohibitionNonCharacterCodePoints(unassignedCodepoint) &&
!StringPrep.prohibitionPrivateUse(unassignedCodepoint) &&
!StringPrep.prohibitionSurrogateCodes(unassignedCodepoint) &&
!StringPrep.prohibitionTaggingCharacters(unassignedCodepoint)) {
break;
}
}
String withUnassignedChar = "abc"+new String(Character.toChars(unassignedCodepoint));
//Assert.assertEquals(withUnassignedChar, saslPrepQuery(withUnassignedChar));
try {
SaslPrep.saslPrep(withUnassignedChar, true);
Assert.fail("Should thow IllegalArgumentException");
} catch (IllegalArgumentException e) {
Assert.assertEquals("Prohibited character ", e.getMessage());
}
}
} scram-2.1/common/src/test/java/com/ongres/scram/common/stringprep/StringPreparationTest.java 0000664 0000000 0000000 00000020107 13535653744 0032502 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.stringprep;
import org.junit.Test;
import java.util.Random;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class StringPreparationTest {
private static final String[] ONLY_NON_PRINTABLE_STRINGS = new String[] { " ", (char) 13 + "", (char) 13 + " " };
@Test
public void doNormalizeNullEmpty() {
String[] nullEmpty = new String[] { null, "" };
int n = 0;
for(StringPreparation stringPreparation : StringPreparations.values()) {
for(String s : nullEmpty) {
try {
stringPreparation.normalize(s);
} catch (IllegalArgumentException e) {
n++;
}
}
}
assertTrue(
"IllegalArgumentException not thrown for either null or empty input",
n == nullEmpty.length * StringPreparations.values().length
);
}
@Test
public void doNormalizeValidAsciiCases() {
// 200 usernames from http://jimpix.co.uk/words/random-username-list.asp
String[] validAsciiUsernames = new String[] {
"toastingxenotime", "infecttolerant", "cobblerjack", "zekedigital", "freshscarisdale", "lamwaylon",
"lagopodousmonkeys", "fanfarecheesy", "willowfinnegan", "canoeamoeba", "stinkeroddball", "terracecomet",
"cakebrazos", "headersidesaddle", "cloudultracrepidarian", "grimegastropub", "stallchilli",
"shawnapentagon", "chapeltarp", "rydbergninja", "differencegym", "europiummuscle", "swilledonce",
"defensivesyntaxis", "desktopredundant", "stakingsky", "goofywaiting", "boundsemm", "pipermonstrous",
"faintfrog", "riskinsist", "constantjunkie", "rejectbroth", "ceilbeau", "ponyjaialai", "burnishselfies",
"unamusedglenmore", "parmesanporcupine", "suteconcerto", "ribstony", "sassytwelve", "coursesnasturtium",
"singlecinders", "kinkben", "chiefpussface", "unknownivery", "robterra", "wearycubes", "bearcontent",
"aquifertrip", "insulinlick", "batterypeace", "rubigloo", "fixessnizort", "coalorecheesy", "logodarthvader",
"equipmentbizarre", "charitycolne", "gradecomputer", "incrediblegases", "ingotflyingfish", "abaftmounting",
"kissingfluke", "chesterdinky", "anthropicdip", "portalcairo", "purebredhighjump", "jamaicansteeping",
"skaterscoins", "chondrulelocust", "modespretty", "otisnadrid", "lagoonone", "arrivepayday", "lawfulpatsy",
"customersdeleted", "superiorarod", "abackwarped", "footballcyclic", "sawtshortstop", "waskerleysanidine",
"polythenehead", "carpacciosierra", "gnashgabcheviot", "plunkarnisdale", "surfacebased", "wickedpark",
"capitalistivan", "kinglassmuse", "adultsceiriog", "medrones", "climaxshops", "archeangolfer", "tomfront",
"kobeshift", "nettleaugustus", "bitesizedlion", "crickedbunting", "englishrichard", "dangerousdelmonico",
"sparklemicrosoft", "kneepadsfold", "enunciatesunglasses", "parchmentsteak", "meigpiton", "puttingcitrusy",
"eyehash", "newtonatomiser", "witchesburberry", "positionwobbly", "clipboardamber", "ricolobster",
"calendarpetal", "shinywound", "dealemral", "moonrakerfinnish", "banditliberated", "whippedfanatical",
"jargongreasy", "yumlayla", "dwarfismtransition", "doleriteduce", "sikickball",
"columngymnastics", "draybowmont", "jupitersnorkling", "siderealmolding", "dowdyrosary", "novaskeeter",
"whickerpulley", "rutlandsliders", "categoryflossed", "coiltiedogfish", "brandwaren", "altairlatigo",
"acruxyouthscape", "harmonicdash", "jasperserver", "slicedaggie", "gravityfern", "bitsstorm",
"readymadehobby", "surfeitgrape", "pantheonslabs", "ammandecent", "skicrackers", "speyfashions",
"languagedeeno", "pettyconfit", "minutesshimmering", "thinhopeangellist", "sleevelesscadmium", "controlarc",
"robinvolvox", "postboxskylark", "tortepleasing", "lutzdillinger", "amnioteperl", "burntmaximize",
"gamblingearn", "bumsouch", "coronagraphdown", "bodgeelearning", "hackingscraper", "hartterbium",
"mindyurgonian", "leidlebalki", "labelthumbs", "lincolncrisps", "pearhamster", "termsfiona",
"tickingsomber", "hatellynfi", "northumberlandgrotesque", "harpistcaramel", "gentryswiss", "illusionnooks",
"easilyrows", "highgluten", "backedallegiance", "laelsitesearch", "methodfix", "teethminstral",
"chemicalchildish", "likablepace", "alikealeph", "nalasincere", "investbaroque", "conditionenvelope",
"splintsmccue", "carnonprompt", "resultharvey", "acceptsheba", "redditmonsoon", "multiplepostbox",
"invitationchurch", "drinksgaliath", "ordersvivid", "mugsgit", "clumpingfreak"
};
for(StringPreparation stringPreparation : StringPreparations.values()) {
for(String s : validAsciiUsernames) {
assertEquals(s, stringPreparation.normalize(s));
}
}
}
/*
* Some simple random testing won't hurt. If a test would fail, create new test with the generated word.
*/
@Test
public void doNormalizeValidAsciiRandom() {
int n = 10 * 1000;
int maxLenght = 64;
Random random = new Random();
String[] values = new String[n];
for(int i = 0; i < n; i++) {
char[] charValue = new char[random.nextInt(maxLenght) + 1];
for(int j = 0; j < charValue.length; j++) {
charValue[j] = (char) (random.nextInt(127 - 33) + 33);
}
values[i] = new String(charValue);
}
for(StringPreparation stringPreparation : StringPreparations.values()) {
for(String s : values) {
assertEquals(
"'" + s + "' is a printable ASCII string, should not be changed by normalize()",
s,
stringPreparation.normalize(s)
);
}
}
}
@Test
public void doNormalizeNoPreparationEmptyAfterNormalization() {
int n = 0;
for(String s : ONLY_NON_PRINTABLE_STRINGS) {
try {
StringPreparations.NO_PREPARATION.normalize(s);
} catch (IllegalArgumentException e) {
n++;
}
}
assertTrue(
"IllegalArgumentException not thrown for either null or empty output after normalization",
n == ONLY_NON_PRINTABLE_STRINGS.length
);
}
@Test
public void doNormalizeNoPreparationNonEmptyAfterNormalization() {
// No exception should be thrown
for(String s : ONLY_NON_PRINTABLE_STRINGS) {
StringPreparations.NO_PREPARATION.normalize(s + "a");
}
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/util/ 0000775 0000000 0000000 00000000000 13535653744 0024104 5 ustar 00root root 0000000 0000000 scram-2.1/common/src/test/java/com/ongres/scram/common/util/AbstractCharAttributeValueTest.java 0000664 0000000 0000000 00000006614 13535653744 0033040 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
import org.junit.Test;
import static org.junit.Assert.*;
public class AbstractCharAttributeValueTest {
private class MockCharAttribute implements CharAttribute {
private final char c;
public MockCharAttribute(char c) {
this.c = c;
}
@Override
public char getChar() {
return c;
}
}
@Test
public void constructorNullAttribute() {
try {
assertNotNull(new AbstractCharAttributeValue((CharAttribute) null, "value"));
} catch(IllegalArgumentException e) {
return;
}
fail("IllegalArgumentException must be thrown if the CharAttribute is null");
}
@Test
public void constructorEmptyValue() {
try {
assertNotNull(new AbstractCharAttributeValue(new MockCharAttribute('c'), ""));
} catch(IllegalArgumentException e) {
return;
}
fail("IllegalArgumentException must be thrown if the value is empty");
}
@Test
public void writeToNonNullValues() {
String[] legalValues = new String[] { "a", "----", "value" };
char c = 'c';
for(String s : legalValues) {
assertEquals(
"" + c + '=' + s,
new AbstractCharAttributeValue(new MockCharAttribute(c), s).toString()
);
}
}
@Test
public void writeToNullValue() {
char c = 'd';
assertEquals(
"" + c,
new AbstractCharAttributeValue(new MockCharAttribute(c), null).toString()
);
}
@Test
public void writeToEscapedValues() {
char c = 'a';
MockCharAttribute mockCharAttribute = new MockCharAttribute(c);
String[] values = new String[] { "a=b", "c,a", ",", "=,", "=,,=" };
for(int i = 0; i < values.length; i++) {
assertEquals(
"" + c + '=' + values[i],
new AbstractCharAttributeValue(mockCharAttribute, values[i]).toString()
);
}
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/util/Base64Test.java 0000664 0000000 0000000 00000005531 13535653744 0026637 0 ustar 00root root 0000000 0000000 /*
* Copyright 2019, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
import java.nio.charset.StandardCharsets;
import org.junit.Assert;
import org.junit.Test;
import com.ongres.scram.common.bouncycastle.base64.Base64;
public class Base64Test {
@Test
public void rfcTest() {
Assert.assertEquals("", new String(Base64.decode(""), StandardCharsets.UTF_8));
Assert.assertEquals("f", new String(Base64.decode("Zg=="), StandardCharsets.UTF_8));
Assert.assertEquals("fo", new String(Base64.decode("Zm8="), StandardCharsets.UTF_8));
Assert.assertEquals("foo", new String(Base64.decode("Zm9v"), StandardCharsets.UTF_8));
Assert.assertEquals("foob", new String(Base64.decode("Zm9vYg=="), StandardCharsets.UTF_8));
Assert.assertEquals("fooba", new String(Base64.decode("Zm9vYmE="), StandardCharsets.UTF_8));
Assert.assertEquals("foobar", new String(Base64.decode("Zm9vYmFy"), StandardCharsets.UTF_8));
Assert.assertEquals("", Base64.toBase64String("".getBytes(StandardCharsets.UTF_8)));
Assert.assertEquals("Zg==", Base64.toBase64String("f".getBytes(StandardCharsets.UTF_8)));
Assert.assertEquals("Zm8=", Base64.toBase64String("fo".getBytes(StandardCharsets.UTF_8)));
Assert.assertEquals("Zm9v", Base64.toBase64String("foo".getBytes(StandardCharsets.UTF_8)));
Assert.assertEquals("Zm9vYg==", Base64.toBase64String("foob".getBytes(StandardCharsets.UTF_8)));
Assert.assertEquals("Zm9vYmE=", Base64.toBase64String("fooba".getBytes(StandardCharsets.UTF_8)));
Assert.assertEquals("Zm9vYmFy", Base64.toBase64String("foobar".getBytes(StandardCharsets.UTF_8)));
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/util/CryptoUtilTest.java 0000664 0000000 0000000 00000004537 13535653744 0027736 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
import org.junit.Test;
import java.security.SecureRandom;
import java.util.Random;
import static org.junit.Assert.fail;
public class CryptoUtilTest {
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
@Test(expected = IllegalArgumentException.class)
public void nonceInvalidSize1() {
CryptoUtil.nonce(0, SECURE_RANDOM);
}
@Test(expected = IllegalArgumentException.class)
public void nonceInvalidSize2() {
CryptoUtil.nonce(-1, SECURE_RANDOM);
}
@Test
public void nonceValid() {
int nNonces = 1000;
int nonceMaxSize = 100;
Random random = new Random();
// Some more random testing
for(int i = 0; i < nNonces; i++) {
for(char c : CryptoUtil.nonce(random.nextInt(nonceMaxSize) + 1, SECURE_RANDOM).toCharArray()) {
if(c == ',' || c < (char) 33 || c > (char) 126) {
fail("Character c='" + c + "' is not allowed on a nonce");
}
}
}
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/util/StringWritableCsvTest.java 0000664 0000000 0000000 00000013164 13535653744 0031230 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
import com.ongres.scram.common.ScramAttributes;
import com.ongres.scram.common.ScramAttributeValue;
import com.ongres.scram.common.gssapi.Gs2AttributeValue;
import com.ongres.scram.common.gssapi.Gs2Attributes;
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class StringWritableCsvTest {
private static final String[] ONE_ARG_VALUES = new String[] { "c=channel", "i=4096", "a=authzid", "n" };
private static final String SEVERAL_VALUES_STRING = "n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL";
@Test
public void writeToNullOrEmpty() {
assertTrue(StringWritableCsv.writeTo(new StringBuffer()).length() == 0);
assertTrue(StringWritableCsv.writeTo(new StringBuffer(), new CharAttributeValue[]{}).length() == 0);
}
@Test
public void writeToOneArg() {
CharAttributeValue[] pairs = new CharAttributeValue[] {
new ScramAttributeValue(ScramAttributes.CHANNEL_BINDING, "channel"),
new ScramAttributeValue(ScramAttributes.ITERATION, "" + 4096),
new Gs2AttributeValue(Gs2Attributes.AUTHZID, "authzid"),
new Gs2AttributeValue(Gs2Attributes.CLIENT_NOT, null)
};
for(int i = 0; i < pairs.length; i++) {
assertEquals(ONE_ARG_VALUES[i], StringWritableCsv.writeTo(new StringBuffer(), pairs[i]).toString());
}
}
@Test
public void writeToSeveralArgs() {
assertEquals(
SEVERAL_VALUES_STRING,
StringWritableCsv.writeTo(
new StringBuffer(),
new Gs2AttributeValue(Gs2Attributes.CLIENT_NOT, null),
null,
new ScramAttributeValue(ScramAttributes.USERNAME, "user"),
new ScramAttributeValue(ScramAttributes.NONCE, "fyko+d2lbbFgONRv9qkxdawL")
).toString()
);
}
@Test
public void parseFromEmpty() {
assertArrayEquals(new String[]{}, StringWritableCsv.parseFrom(""));
}
@Test
public void parseFromOneArgWithLimitsOffsets() {
for(String s : ONE_ARG_VALUES) {
assertArrayEquals(new String[] {s}, StringWritableCsv.parseFrom(s));
}
int[] numberEntries = new int[] { 0, 1 };
for(int n : numberEntries) {
for(String s : ONE_ARG_VALUES) {
assertArrayEquals(new String[] {s}, StringWritableCsv.parseFrom(s, n));
}
}
for(String s : ONE_ARG_VALUES) {
assertArrayEquals(new String[] {s, null, null}, StringWritableCsv.parseFrom(s, 3));
}
for(int n : numberEntries) {
for(String s : ONE_ARG_VALUES) {
assertArrayEquals(new String[] {s}, StringWritableCsv.parseFrom(s, n, 0));
}
}
for(String s : ONE_ARG_VALUES) {
assertArrayEquals(new String[] {s, null, null}, StringWritableCsv.parseFrom(s, 3, 0));
}
for(int n : numberEntries) {
for(String s : ONE_ARG_VALUES) {
assertArrayEquals(new String[] { null }, StringWritableCsv.parseFrom(s, n, 1));
}
}
}
@Test
public void parseFromSeveralArgsWithLimitsOffsets() {
assertArrayEquals(
new String[] { "n", "", "n=user", "r=fyko+d2lbbFgONRv9qkxdawL" },
StringWritableCsv.parseFrom(SEVERAL_VALUES_STRING)
);
assertArrayEquals(
new String[] { "n", "" },
StringWritableCsv.parseFrom(SEVERAL_VALUES_STRING, 2)
);
assertArrayEquals(
new String[] { "", "n=user" },
StringWritableCsv.parseFrom(SEVERAL_VALUES_STRING, 2, 1)
);
assertArrayEquals(
new String[] { "r=fyko+d2lbbFgONRv9qkxdawL", null },
StringWritableCsv.parseFrom(SEVERAL_VALUES_STRING, 2, 3)
);
assertArrayEquals(
new String[] { null, null },
StringWritableCsv.parseFrom(SEVERAL_VALUES_STRING, 2, 4)
);
assertArrayEquals(
new String[] { "n", "", "n=user", "r=fyko+d2lbbFgONRv9qkxdawL", null },
StringWritableCsv.parseFrom(SEVERAL_VALUES_STRING, 5)
);
}
}
scram-2.1/common/src/test/java/com/ongres/scram/common/util/UsAsciiUtilsTest.java 0000664 0000000 0000000 00000006410 13535653744 0030171 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017, OnGres.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.ongres.scram.common.util;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.*;
public class UsAsciiUtilsTest {
@Test
public void toPrintableNull() {
try {
UsAsciiUtils.toPrintable(null);
} catch(IllegalArgumentException ex) {
return;
}
fail("Calling with null value must throw IllegalArgumentException");
}
@Test
public void toPrintableNonASCII() {
String[] nonASCIIStrings = new String[] { "abcdé", "ñ", "€", "Наташа", (char) 127 + "" };
int n = 0;
for(String s : nonASCIIStrings) {
try {
UsAsciiUtils.toPrintable(s);
} catch(IllegalArgumentException ex) {
n++;
}
}
assertTrue(
"String(s) with non-ASCII characters not throwing IllegalArgumentException",
n == nonASCIIStrings.length
);
}
@Test
public void toPrintableNonPrintable() {
String[] original = new String[] { " u ", "a" + (char) 12, (char) 0 + "ttt" + (char) 31 };
String[] expected = new String[] { "u", "a", "ttt" };
for(int i = 0; i < original.length; i++) {
assertEquals("", expected[i], UsAsciiUtils.toPrintable(original[i]));
}
}
@Test
public void toPrintableAllPrintable() {
List values = new ArrayList();
values.addAll(Arrays.asList(
new String[] { (char) 33 + "", "user", "!", "-,.=?", (char) 126 + "" })
);
for(int c = 33; c < 127; c++) {
values.add("---" + (char) c + "---");
}
for(String s : values) {
assertEquals(
"All printable String '" + s + "' not returning the same value",
s,
UsAsciiUtils.toPrintable(s)
);
}
}
}
scram-2.1/mvnw 0000775 0000000 0000000 00000023666 13535653744 0013432 0 ustar 00root root 0000000 0000000 #!/bin/sh
# ----------------------------------------------------------------------------
# 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.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" "-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
"-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
scram-2.1/mvnw.cmd 0000664 0000000 0000000 00000014721 13535653744 0014161 0 ustar 00root root 0000000 0000000 @REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%
scram-2.1/pom.xml 0000664 0000000 0000000 00000022133 13535653744 0014016 0 ustar 00root root 0000000 0000000
4.0.0com.ongres.scramparent2.1pomcommonclientSCRAMJava Implementation of the Salted Challenge Response Authentication Mechanism (SCRAM)https://gitlab.com/ongresinc/scram2019com.ongres.ahtÁlvaro Hernández Tortosaaht@ongres.comcom.ongres.matteomMatteo Mellimatteom@ongres.comcom.ongres.begonaBegoña Pérez Martínbegonapm@ongres.comThe 2-Clause BSD Licensehttps://opensource.org/licenses/BSD-2-Clausereposcm:git:https://gitlab.com/ongresinc/scram.gitscm:git:git@gitlab.com:ongresinc/scram.gitgit@gitlab.com:ongresinc/scram.gitGitLabhttps://gitlab.com/ongresinc/scram/issuesossrh-releaseOSSRH Release repositoryhttps://oss.sonatype.org/service/local/staging/deploy/maven2ossrh-snapshotOSSRH Snapshot repositoryhttps://oss.sonatype.org/content/repositories/snapshotsUTF-81.7common/spotbugs-exclude.xmljunitjunit4.12com.google.code.findbugsannotations3.0.1providedcom.google.code.findbugsjsr3053.0.1providedorg.apache.maven.pluginsmaven-compiler-plugin3.6.1${java.version}${java.version}-Xlint:all-Xlint:-optionstruetrueorg.apache.maven.pluginsmaven-source-plugin3.0.1attach-sourcesjar-no-forkorg.apache.maven.pluginsmaven-javadoc-plugin2.10.4attach-javadocsjar7saferorg.codehaus.mojofindbugs-maven-plugin3.0.4MaxLowtrue${spotbugs.excluded.location}${project.build.directory}/findbugsanalyze-compilecheckmaster-branchorg.apache.maven.pluginsmaven-enforcer-plugin1.4.1enforce-releaseenforceArtifacts on master branch must not be snapshot!releaseorg.sonatype.pluginsnexus-staging-maven-plugin1.6.8trueossrhhttps://oss.sonatype.org/trueorg.apache.maven.pluginsmaven-gpg-plugin1.6sign-artifactsverifysignsoftware@ongres.com
scram-2.1/thirdparty/ 0000775 0000000 0000000 00000000000 13535653744 0014672 5 ustar 00root root 0000000 0000000 scram-2.1/thirdparty/bouncycastle-LICENSE 0000664 0000000 0000000 00000002135 13535653744 0020371 0 ustar 00root root 0000000 0000000 Copyright (c) 2000 - 2019 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. scram-2.1/thirdparty/passlib_lambda-LICENSE 0000664 0000000 0000000 00000002113 13535653744 0020627 0 ustar 00root root 0000000 0000000
The MIT License
Copyright (c) 2010-2016 Google, Inc. http://angularjs.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. scram-2.1/thirdparty/saslprep-LICENSE 0000664 0000000 0000000 00000002355 13535653744 0017533 0 ustar 00root root 0000000 0000000 Copyright 2019, OnGres.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.