Skip to content

Commit 9598a93

Browse files
committed
SecurityAPI repository migration.
1 parent 224467a commit 9598a93

24 files changed

+2150
-0
lines changed

pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
<software.azure.cosmos.version>4.42.0</software.azure.cosmos.version>
2929
<log4j.version>2.21.1</log4j.version>
3030
<io.opentelemetry.version>1.28.0</io.opentelemetry.version>
31+
<org.bouncycastle.version>1.78.1</org.bouncycastle.version>
3132
</properties>
3233

3334
<organization>
@@ -114,6 +115,7 @@
114115
<module>gxcloudstorage-tests</module>
115116
<module>gxobservability</module>
116117
<module>gxcloudstorage-awss3-v2</module>
118+
<module>securityapicommons</module>
117119
</modules>
118120

119121
<dependencies>

securityapicommons/pom.xml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>com.genexus</groupId>
8+
<artifactId>parent</artifactId>
9+
<version>${revision}${changelist}</version>
10+
</parent>
11+
12+
<artifactId>securityapicommons</artifactId>
13+
<name>GeneXus Security API Commons</name>
14+
<dependencies>
15+
16+
17+
<dependency>
18+
<groupId>org.bouncycastle</groupId>
19+
<artifactId>bcpkix-jdk18on</artifactId>
20+
<version>${org.bouncycastle.version}</version>
21+
</dependency>
22+
<dependency>
23+
<groupId>org.bouncycastle</groupId>
24+
<artifactId>bcprov-jdk18on</artifactId>
25+
<version>${org.bouncycastle.version}</version>
26+
</dependency>
27+
</dependencies>
28+
29+
<build>
30+
<finalName>SecurityAPICommons</finalName>
31+
<plugins>
32+
<plugin>
33+
<groupId>org.apache.maven.plugins</groupId>
34+
<artifactId>maven-compiler-plugin</artifactId>
35+
<version>3.8.0</version>
36+
</plugin>
37+
</plugins>
38+
</build>
39+
40+
</project>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.genexus.securityapicommons.commons;
2+
3+
public abstract class Certificate extends PublicKey {
4+
5+
public Certificate() {
6+
super();
7+
}
8+
9+
public abstract boolean load(String path);
10+
public abstract boolean loadPKCS12(String path, String alias, String password);
11+
public abstract boolean fromBase64(String base64Data);
12+
public abstract String toBase64();
13+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
2+
package com.genexus.securityapicommons.commons;
3+
4+
/**
5+
* @author sgrampone
6+
*
7+
*/
8+
public class Error {
9+
10+
private boolean exists;
11+
private String code;
12+
private String description;
13+
14+
/**
15+
* @return error code string
16+
*/
17+
public String getCode() {
18+
return code;
19+
}
20+
21+
/**
22+
* @return error description string
23+
*/
24+
public String getDescription() {
25+
return description;
26+
}
27+
28+
/**
29+
* Error constructor
30+
*/
31+
public Error() {
32+
this.exists = false;
33+
this.code = "";
34+
this.description = "";
35+
}
36+
37+
public Error(String code, String description)
38+
{
39+
this.code = code;
40+
this.description = description;
41+
this.exists = true;
42+
}
43+
44+
/**
45+
* Set error values
46+
*
47+
* @param errorCode
48+
* String error internal code
49+
* @param errorDescription
50+
* String error internal description
51+
*/
52+
public void setError(String errorCode, String errorDescription) {
53+
this.exists = true;
54+
this.code = errorCode;
55+
this.description = errorDescription;
56+
57+
}
58+
59+
/**
60+
* If an error exists
61+
*
62+
* @return 1 if an error exists, 0 if not
63+
*/
64+
public boolean existsError() {
65+
return this.exists;
66+
}
67+
68+
/**
69+
* Sets initial parameters
70+
*/
71+
public void cleanError() {
72+
this.exists = false;
73+
this.code = "";
74+
this.description = "";
75+
}
76+
77+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.genexus.securityapicommons.commons;
2+
3+
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
4+
5+
public class Key extends SecurityAPIObject {
6+
7+
public Key() {
8+
super();
9+
}
10+
11+
protected String algorithm;
12+
13+
public String getAlgorithm()
14+
{
15+
return this.algorithm;
16+
}
17+
18+
public boolean load(String path) {return false; }
19+
public boolean loadPKCS12(String path, String alias, String password) { return false; }
20+
public boolean fromBase64(String base64) { return false; }
21+
public String toBase64() { return ""; }
22+
protected void setAlgorithm() {}
23+
public AsymmetricKeyParameter getAsymmetricKeyParameter() {return null; }
24+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.genexus.securityapicommons.commons;
2+
3+
public abstract class PrivateKey extends Key{
4+
5+
public PrivateKey() {
6+
super();
7+
}
8+
9+
public abstract boolean loadEncrypted(String privateKeyPath, String encryptionPassword);
10+
}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
package com.genexus.securityapicommons.commons;
2+
3+
import java.io.File;
4+
import java.io.FileReader;
5+
import java.io.IOException;
6+
import java.security.KeyFactory;
7+
import java.security.spec.X509EncodedKeySpec;
8+
9+
import org.bouncycastle.asn1.ASN1Sequence;
10+
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
11+
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
12+
import org.bouncycastle.cert.X509CertificateHolder;
13+
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
14+
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
15+
import org.bouncycastle.crypto.params.RSAKeyParameters;
16+
import org.bouncycastle.crypto.util.PublicKeyFactory;
17+
import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
18+
import org.bouncycastle.openssl.PEMKeyPair;
19+
import org.bouncycastle.openssl.PEMParser;
20+
import org.bouncycastle.util.encoders.Base64;
21+
22+
import com.genexus.securityapicommons.utils.SecurityUtils;
23+
24+
public class PublicKey extends Key {
25+
26+
protected SubjectPublicKeyInfo subjectPublicKeyInfo;
27+
28+
public PublicKey() {
29+
super();
30+
}
31+
32+
/******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/
33+
@Override
34+
public boolean load(String path) {
35+
36+
/******* INPUT VERIFICATION - BEGIN *******/
37+
SecurityUtils.validateStringInput("path", path, this.error);
38+
if (!(SecurityUtils.extensionIs(path, ".pem") || SecurityUtils.extensionIs(path, "key"))) {
39+
this.error.setError("PU001", "Public key should be loaded from a .pem or .key file");
40+
return false;
41+
}
42+
/******* INPUT VERIFICATION - END *******/
43+
boolean loaded = false;
44+
try {
45+
loaded = loadPublicKeyFromFile(path);
46+
} catch (Exception e) {
47+
this.error.setError("PU002", e.getMessage());
48+
return false;
49+
}
50+
return loaded;
51+
}
52+
53+
@Override
54+
public boolean fromBase64(String base64Data) {
55+
56+
/******* INPUT VERIFICATION - BEGIN *******/
57+
SecurityUtils.validateStringInput("base64Data", base64Data, this.error);
58+
if (this.hasError()) {
59+
return false;
60+
}
61+
62+
/******* INPUT VERIFICATION - END *******/
63+
64+
boolean flag;
65+
try {
66+
byte[] dataBuffer = Base64.decode(base64Data);
67+
this.subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(dataBuffer));
68+
flag = true;
69+
} catch (Exception e) {
70+
this.error.setError("PU003", e.getMessage());
71+
flag = false;
72+
}
73+
setAlgorithm();
74+
75+
return flag;
76+
}
77+
78+
@Override
79+
public String toBase64() {
80+
if (this.subjectPublicKeyInfo == null) {
81+
this.error.setError("PU004", "Not loaded key");
82+
return "";
83+
}
84+
String base64Encoded = "";
85+
86+
try {
87+
base64Encoded = new String(Base64.encode(this.subjectPublicKeyInfo.getEncoded()));
88+
89+
} catch (Exception e) {
90+
this.error.setError("PU005", e.getMessage());
91+
}
92+
93+
return base64Encoded;
94+
}
95+
96+
/******** EXTERNAL OBJECT PUBLIC METHODS - END ********/
97+
98+
@Override
99+
protected void setAlgorithm() {
100+
if (this.subjectPublicKeyInfo == null) {
101+
return;
102+
}
103+
String alg = this.subjectPublicKeyInfo.getAlgorithm().getAlgorithm().getId();
104+
switch (alg) {
105+
case "1.2.840.113549.1.1.1":
106+
this.algorithm = "RSA";
107+
break;
108+
case "1.2.840.10045.2.1":
109+
this.algorithm = "ECDSA";
110+
break;
111+
}
112+
113+
}
114+
115+
@Override
116+
public AsymmetricKeyParameter getAsymmetricKeyParameter() {
117+
AsymmetricKeyParameter akp = null;
118+
try {
119+
akp = PublicKeyFactory.createKey(this.subjectPublicKeyInfo);
120+
} catch (Exception e) {
121+
this.error.setError("PU006", e.getMessage());
122+
return null;
123+
}
124+
return akp;
125+
}
126+
127+
/**
128+
* @return PublicKey type for the key type
129+
*/
130+
public java.security.PublicKey getPublicKey() {
131+
java.security.PublicKey pk = null;
132+
try {
133+
KeyFactory kf = SecurityUtils.getKeyFactory(this.algorithm);
134+
X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(this.subjectPublicKeyInfo.getEncoded());
135+
pk = kf.generatePublic(encodedKeySpec);
136+
} catch (Exception e) {
137+
this.error.setError("PU007", e.getMessage());
138+
return null;
139+
}
140+
return pk;
141+
}
142+
143+
private boolean loadPublicKeyFromFile(String path) throws IOException {
144+
boolean flag = false;
145+
try (FileReader privateKeyReader = new FileReader(new File(path))) {
146+
try (PEMParser parser = new PEMParser(privateKeyReader)) {
147+
Object obj;
148+
obj = parser.readObject();
149+
if (obj instanceof PrivateKeyInfo) {
150+
this.error.setError("PU008", "The file contains a private key");
151+
flag = false;
152+
}
153+
if (obj instanceof SubjectPublicKeyInfo) {
154+
this.subjectPublicKeyInfo = (SubjectPublicKeyInfo) obj;
155+
setAlgorithm();
156+
flag = true;
157+
}
158+
if (obj instanceof PEMKeyPair) {
159+
PEMKeyPair keypair = (PEMKeyPair) obj;
160+
this.subjectPublicKeyInfo = keypair.getPublicKeyInfo();
161+
setAlgorithm();
162+
flag = true;
163+
}
164+
if (obj instanceof ECPublicKeyParameters) {
165+
ECPublicKeyParameters ecParms = (ECPublicKeyParameters) obj;
166+
this.subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(ecParms);
167+
setAlgorithm();
168+
flag = true;
169+
}
170+
if (obj instanceof RSAKeyParameters) {
171+
RSAKeyParameters rsaParms = (RSAKeyParameters) obj;
172+
this.subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(rsaParms);
173+
setAlgorithm();
174+
flag = true;
175+
}
176+
if (obj instanceof X509CertificateHolder) {
177+
this.error.setError("PU009", "This file contains a certificate, use the Certificate object instead");
178+
flag = false;
179+
}
180+
}
181+
}
182+
if (!flag && !this.hasError()) {
183+
this.error.setError("PU010", "Error loading public key from file");
184+
}
185+
return flag;
186+
}
187+
188+
}

0 commit comments

Comments
 (0)