Copy a CRL that was created in Go - java

I created a CRL in Go (parsed it into PEM) and now I want to re-create the exact same CRL in Java (to obtain the same PEM). However, I'm not sure how to do this, I find that the CRL classes in Go and Java are very different.
I created the CRL in Golang the following way:
var revokedCerts []pkix.RevokedCertificate
clientRevocation := pkix.RevokedCertificate{
SerialNumber: clientCert.SerialNumber,
RevocationTime: timeToUseInRevocation.UTC(),
}
revokedCerts = append(revokedCerts, clientRevocation)
crlSubject := pkix.Name{
Organization: []string{"testorg", "TestOrg"},
StreetAddress: []string{"TestAddress"},
PostalCode: []string{"0"},
Province: []string{"TestProvince"},
Locality: []string{"TestLocality"},
Country: []string{"TestCountry"},
CommonName: "Test Name",
}
var sigAlgorithm pkix.AlgorithmIdentifier
sigAlgorithm.Algorithm = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
sigAlgorithm.Parameters = asn1.NullRawValue
tbsCertList := pkix.TBSCertificateList{
Version: 1,
Signature: sigAlgorithm,
Issuer: crlSubject.ToRDNSequence(),
ThisUpdate: timeToUseInRevocation,
NextUpdate: timeToUseInRevocation.Add(time.Millisecond * time.Duration(86400000)),
RevokedCertificates: revokedCerts,
}
newCRL, err := asn1.Marshal(pkix.CertificateList{
TBSCertList: tbsCertList, // new CRL
SignatureAlgorithm: sigAlgorithm,
SignatureValue: asn1.BitString{},
})
crlCreated, err := x509.ParseCRL(newCRL)
//CRL pem Block
crlPemBlock := &pem.Block{
Type: "X509 CRL",
Bytes: newCRL,
}
var crlBuffer bytes.Buffer
err = pem.Encode(&crlBuffer, crlPemBlock)
I want to reproduce this in Java.
I am aware that I have variables (e.g. crl signature) that are empty/nil. That is for the purpose of what I want to do.
I could take the PEM and read to a CRL in Java but I'm not being able to do so to create the exact same CRL.
I want to create the CRL in Java also without a signature (all parameters equal).

Related

React jest and MSAL getting BrowserAuthError : crypto

I'm trying to test a few components that are using MSAL for authentication.
Thus far, I have a simple test, which test if my component can render, as follows:
// <MsalInstanceSnippet>
const msalInstance = new PublicClientApplication({
auth: {
clientId: config.appId,
redirectUri: config.redirectUri
},
cache: {
cacheLocation: 'sessionStorage',
storeAuthStateInCookie: true
}
});
When I run the test, I'm getting the following error:
BrowserAuthError: crypto_nonexistent: The crypto object or function is not available. Detail:Browser crypto or msCrypto object not available.
10 |
11 | // <MsalInstanceSnippet>
> 12 | const msalInstance = new PublicClientApplication({
| ^
13 | auth: {
14 | clientId: config.appId,
15 | redirectUri: config.redirectUri
at BrowserAuthError.AuthError [as constructor] (node_modules/#azure/msal-common/dist/error/AuthError.js:27:24)
at new BrowserAuthError (node_modules/#azure/msal-browser/src/error/BrowserAuthError.ts:152:9)
at Function.Object.<anonymous>.BrowserAuthError.createCryptoNotAvailableError (node_modules/#azure/msal-browser/src/error/BrowserAuthError.ts:172:16)
at new BrowserCrypto (node_modules/#azure/msal-browser/src/crypto/BrowserCrypto.ts:31:36)
at new CryptoOps (node_modules/#azure/msal-browser/src/crypto/CryptoOps.ts:45:30)
at PublicClientApplication.ClientApplication (node_modules/#azure/msal-browser/src/app/ClientApplication.ts:108:58)
at new PublicClientApplication (node_modules/#azure/msal-browser/src/app/PublicClientApplication.ts:49:9)
at Object.<anonymous> (src/App.test.tsx:12:22)
I'm unsure what the above means, but as far as I can understand, this error is occurring because the session is not authenticated.
My question can therefore be divided into the following:
What does this error mean?
How can I solve this error? (Can we bypass MSAL by any chance for testing purposes?)
You need to add crypto to your Jest config in jest.config.js:
module.exports = {
// ...
globals: {
// ...
crypto: require("crypto")
}
};
For eslint issue
try this way
import crypto from 'crypto';
module.exports = {
// ...
globals: {
// ...
crypto,
}
};
I tried adding crypto to my jest.config.js, but it didn't work. Then I tried adding it package.json. It was also pointless giving this error.
Out of the box, Create React App only supports overriding these Jest options:
• clearMocks
• collectCoverageFrom
• coveragePathIgnorePatterns
• coverageReporters
• coverageThreshold
• displayName
• extraGlobals
• globalSetup
• globalTeardown
• moduleNameMapper
• resetMocks
• resetModules
• restoreMocks
• snapshotSerializers
• testMatch
• transform
• transformIgnorePatterns
• watchPathIgnorePatterns.
These options in your package.json Jest configuration are not currently supported by Create React App:
In my case, I have a custom hook that has a dependency with msalInstance
I can prevent the above error by mocking my hook as said here
But still, this wasn't a good solution because if I have many hooks like this. So what I did was mock msalInstance in setupTests.ts file
jest.mock('./msal-instance', () => ({
getActiveAccount: () => ({}),
acquireTokenSilent: () => Promise.resolve({ accessToken: '' }),
}));
This is my msal-instance.ts
import {
PublicClientApplication,
EventType,
EventMessage,
AuthenticationResult,
} from '#azure/msal-browser';
import { msalConfig } from './authConfig';
const msalInstance = new PublicClientApplication(msalConfig);
// Account selection logic is app dependent. Adjust as needed for different use cases.
const accounts = msalInstance.getAllAccounts();
if (accounts.length > 0) {
msalInstance.setActiveAccount(accounts[0]);
}
msalInstance.addEventCallback((event: EventMessage) => {
if (event.eventType === EventType.LOGIN_SUCCESS && event.payload) {
const payload = event.payload as AuthenticationResult;
const { account } = payload;
msalInstance.setActiveAccount(account);
}
});
export default msalInstance;
For react version 17.x.x you can install "#wojtekmaj/enzyme-adapter-react-17" package and after that you can create a src/setupTests.js file. You can add all your environment variables and other configurations to this file as follows:
//This is for the issue above
const nodeCrypto = require("crypto");
window.crypto = {
getRandomValues: function (buffer) {
return nodeCrypto.randomFillSync(buffer);
},
};
//It is also possible to add ENV variables
window.ENV = {
ApiURL: {
lessonsUrl: "https://myApiURL.com/APIendpoint",
}
CloudUiUrl: "localhost:3000",
};
When you run your tests #wojtekmaj/enzyme-adapter-react-17 will take the settings in this file automatically.

sign a SHA-256 hash with DSA in Go

I want to sign a SHA-256 hash with DSA.
Using Java I can write:
Signature sig = Signature.getInstance("SHA256withDSA");
sig.initSign(priKey);
sig.update(new byte[]{1});
byte[] sign = sig.sign();
System.out.println(HexUtil.encodeHexStr(sign));
Using the Go language, I couldn't find any way to resolve it
The only instance of checking a DSAWithSHA256 signature in go is in github.com/avast/apkverifier
case x509.DSAWithSHA256:
hash := sha256.Sum256(signed)
pub := cert.PublicKey.(*dsa.PublicKey)
reqLen := pub.Q.BitLen() / 8
if reqLen > len(hash) {
return fmt.Errorf("Digest algorithm is too short for given DSA parameters.")
}
digest := hash[:reqLen]
dsaSig := new(dsaSignature)
if rest, err := asn1.Unmarshal(signature, dsaSig); err != nil {
return err
} else if len(rest) != 0 {
return errors.New("x509: trailing data after DSA signature")
}
if dsaSig.R.Sign() <= 0 || dsaSig.S.Sign() <= 0 {
return errors.New("x509: DSA signature contained zero or negative values")
}
if !dsa.Verify(pub, digest, dsaSig.R, dsaSig.S) {
return errors.New("x509: DSA verification failure")
}
But actually using the signature algorithm is indeed unsupported, for reason illustrated in github.com/grantae/certinfo
Issues:
Unfortunately, OpenSSL uses non-deterministic signing for DSA and ECDSA certificate requests, so running make-certs.sh will not reproduce the same CSRs despite having static keys.
These files have to be kept in-sync manually.
The x509 package does not currently set CertificateRequest.SignatureAlgorithm for DSA CSRs.
Therefore the 'leaf2.csr.text' contains the line 'Signature Algorithm: 0'
instead of 'Signature Algorithm: DSAWithSHA256' to allow the test to pass and indicate that the problem is with x509 and not this package.
Hence its unsupported status in Go crypto/x509 package.

Difference between Go DSA and Java DSA [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Go generates a signature using a DSA private key
Java verifies first step result using the DSA public key
Java should return true, but returns false
package main
import (
"crypto/dsa"
"crypto/rand"
"encoding/asn1"
"encoding/hex"
"fmt"
"golang.org/x/crypto/ssh"
"math/big"
)
func main() {
// a dsa private key
pemData := []byte("-----BEGIN DSA PRIVATE KEY-----\n" +
"MIIBvAIBAAKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR\n" +
"+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb\n" +
"+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdg\n" +
"UI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlX\n" +
"TAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCj\n" +
"rh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQB\n" +
"TDv+z0kqAoGBAIb9o0KPsjAdzjK571e1Mx7ZhEyJGrcxHiN2sW8IztEbqrKKiMxp\n" +
"NlTwm234uBdtzVHE3uDWZpfHPMIRmwBjCYDFRowWWVRdhdFXZlpCyp1gMWqJ11dh\n" +
"3FI3+O43DevRSyyuLRVCNQ1J3iVgwY5ndRpZU7n6y8DPH4/4EBT7KvnVAhR4Vwun\n" +
"Fhu/+4AGaVeMEa814I3dqg==\n" +
"-----END DSA PRIVATE KEY-----")
// parse dsa
p, _ := ssh.ParseRawPrivateKey(pemData)
pp := p.(*dsa.PrivateKey)
// orign data
hashed := []byte{1}
r, s, _ := dsa.Sign(rand.Reader, pp, hashed)
type dsaSignature struct {
R, S *big.Int
}
var ss dsaSignature
ss.S = s
ss.R = r
signatureBytes, _ := asn1.Marshal(ss)
// print sign
fmt.Println(hex.EncodeToString(signatureBytes))
}
Java reads the DSA public key and initialize a signer
Java verify first step sign result
returns false
#Test
public void ttt() throws InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
// DSA public key
String pubKey = "-----BEGIN PUBLIC KEY-----\n" +
"MIIBuDCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9E\n" +
"AMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f\n" +
"6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv\n" +
"8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtc\n" +
"NrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwky\n" +
"jMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/h\n" +
"WuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYUAAoGBAIb9o0KPsjAdzjK571e1Mx7ZhEyJ\n" +
"GrcxHiN2sW8IztEbqrKKiMxpNlTwm234uBdtzVHE3uDWZpfHPMIRmwBjCYDFRowW\n" +
"WVRdhdFXZlpCyp1gMWqJ11dh3FI3+O43DevRSyyuLRVCNQ1J3iVgwY5ndRpZU7n6\n" +
"y8DPH4/4EBT7KvnV\n" +
"-----END PUBLIC KEY-----";
String publicKeyPEM = pubKey
.replace("-----BEGIN PUBLIC KEY-----\n", "")
.replaceAll(System.lineSeparator(), "")
.replace("-----END PUBLIC KEY-----", "");
byte[] publicEncoded = Base64.decodeBase64(publicKeyPEM);
KeyFactory keyFactory1 = KeyFactory.getInstance("DSA");
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicEncoded);
DSAPublicKey pubKeyy = (DSAPublicKey) keyFactory1.generatePublic(publicKeySpec);
// init signer
Signature sig1 = Signature.getInstance("DSA");
sig1.initVerify(pubKeyy);
sig1.update(new byte[]{1});
// verify first result
System.out.println(sig1.verify(HexUtil.decodeHex("first step result")));
}
i tred to use NONEwithDSA within the Java implementation but it didnt do it
Signature sig1 = Signature.getInstance("NONEwithDSA");
java.security.SignatureException: Data for RawDSA must be exactly 20 bytes long
i tred to use SHA1withDSA within the Java implementation but it didnt do it
Signature sig1 = Signature.getInstance("SHA1withDSA");
returns false
In Java the (Signature) algorithm name DSA is an alias for SHA1withDSA, i.e. the original FIPS186-0 algorithm. This is not the same as the nonstandard 'raw' primitive apparently implemented by Go. NONEwithDSA is indeed the correct Java name for what you want, but the implementation in the 'standard' (SUN) provider is something of a kludge that requires exactly 20 bytes of data, not more or less, because that was the size of the SHA1 hash which was the only standard hash for DSA prior to FIPS186-3.
If you (have or can get and) use the BouncyCastle provider, it does not have this restriction, and should work for your code changed to NONEwithDSA (and either the code or security config modified so that BC is selected as the provider, of course).
If you don't use Bouncy, I think you'll have to code the algorithm yourself; I don't think there's any way to get the SUN implementation to do what you want.
Although it would be better to sign a properly-sized hash as specified in the standard, not raw data, and then you could use the Java providers as specified and designed.

Undefined CommonName in certificate

So far, I've been working with a certificate which I added to a SoapUI 5.2 project and which gave me access to a pre-production server. However, now that I'm ready to move to a production environment, I'm trying to check the new production certificate with SoapUI, but I'm getting the next error:
WARN:Using fallback method to load keystore/truststore due to: Invalid keystore format
ERROR:An error occurred [java.lang.NullPointerException], see error log for details
And the error log says:
ERROR:Could not load keystore/truststore
ERROR:java.lang.NullPointerException
java.lang.NullPointerException
at org.apache.commons.ssl.KeyStoreBuilder.build(KeyStoreBuilder.java:176)
at org.apache.commons.ssl.KeyStoreBuilder.build(KeyStoreBuilder.java:97)
at org.apache.commons.ssl.KeyStoreBuilder.build(KeyStoreBuilder.java:88)
at com.eviware.soapui.impl.wsdl.support.wss.crypto.KeyMaterialWssCrypto.fallbackLoad(KeyMaterialWssCrypto.java:206)
at com.eviware.soapui.impl.wsdl.support.wss.crypto.KeyMaterialWssCrypto.load(KeyMaterialWssCrypto.java:168)
at com.eviware.soapui.impl.wsdl.support.wss.crypto.KeyMaterialWssCrypto.getStatus(KeyMaterialWssCrypto.java:216)
at com.eviware.soapui.impl.wsdl.panels.project.WSSTabPanel$CryptoTableModel.getValueAt(WSSTabPanel.java:643)
at javax.swing.JTable.getValueAt(Unknown Source)
at javax.swing.JTable.prepareRenderer(Unknown Source)
...
The only difference I found between the pre-production and production certificates was that the latter did not have the CommonName field defined.
I know that field is not mandatory, so how is that possible? How can I solve this problem without asking for a new certificate? That's not an option.
Any suggestion would be appreciated.
I check the pom.xml of SOAPUI project for 5.2 versión, and it use not-yet-commons-ssl versión 0.3.11:
<dependency>
<groupId>commons-ssl</groupId>
<artifactId>not-yet-commons-ssl</artifactId>
<version>0.3.11</version>
</dependency>
And If you check the build method for org.apache.commons.ssl.KeyStoreBuilder class as the exception thrown in your error log you'll see:
public static KeyStore build(byte[] jksOrCerts, byte[] privateKey,
char[] jksPassword, char[] keyPassword)
throws IOException, CertificateException, KeyStoreException,
NoSuchAlgorithmException, InvalidKeyException,
NoSuchProviderException, ProbablyBadPasswordException,
UnrecoverableKeyException {
...
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, jksPassword);
Iterator keysIt = keys.iterator();
Iterator chainsIt = chains.iterator();
int i = 1;
while (keysIt.hasNext() && chainsIt.hasNext()) {
Key key = (Key) keysIt.next();
Certificate[] c = (Certificate[]) chainsIt.next();
X509Certificate theOne = buildChain(key, c);
String alias = "alias_" + i++;
// The theOne is not null, then our chain was probably altered.
// Need to trim out the newly introduced null entries at the end of
// our chain.
if (theOne != null) {
c = Certificates.trimChain(c);
alias = Certificates.getCN(theOne);
/* line 176 */ alias = alias.replace(' ', '_');
}
ks.setKeyEntry(alias, key, keyPassword, c);
}
return ks;
}
}
So seems that you're right and the problem is that your certificate has no common name, so org.apache.commons.ssl.Certificates.getCN(X509Certificate) returns null as alias and then alias.replace is throwing the NPE.
alias = Certificates.getCN(theOne);
/* line 176 */ alias = alias.replace(' ', '_');
I don't see nothing that says that Common Name is mandatory in RFC5280, however various code/software use it for different purposes as not-yet-commons-ssl does.
Your certificate is probably right but you can't use it with SOAPUI 5.2 version to test your environment if it hasn't the CN, so if you want to use SOAPUI to test your environment I think that you've to reissue the certificate generating a CSR with CN. Or you can report the problem to http://juliusdavies.ca/commons-ssl/ and then ask to SOAPUI to include the latest version...
Hope this helps,

verify a rsa sign from java in php

Since a few days I've got a problem that I can't solve on my own:
On a JavaCard I generate a RSA KeyPair (length: 1024) and a signature (Mode:ALG_RSA_MD5_PKCS1).
Now I have to verify the signature in php.
From my JavaCard I get the exponent, modulus and the signature in hexadecimal:
$mod = '951ADDA04637190B6202BB52787D3C19160A383C80C2E7242D0A7850FDD80C1CD1CCCF1395F8CA0B20270E3BC6C86F78232D65D148258BEFD0884563C60AB2C327506FB4FA0095CF0B1C527D942155731451F790EC0A227D38613C9EBFB2E04A657B3BA5456B35F71E92E14B7E1CB38DB6572559BFCA3B0AD8AA061D48F68931';
$exp = '010001';
$sign ='75867D42BDE6DF1066D4AF69418FCDD4B0F19173141128DFEBC64AF6C014CB92D38F4824E52BB064A610E07C7783AE57AE993A792F15208FB199CB1F45B64623AACB7FBA07AD89513C8DBA893C9FA6939857AA2CA53AAD99D9A9C1C32DF4E2769FCACB72E2C2C495727D368D953A911D32E79E230751202714DD15C0B6A34782';
$plaintext = '01020304';
A Verification in Java is no problem. But know I have to verify the signature in PHP (I take phpseclib).
In PHP I generate my public_key with CRYPT_RSA_PUBLIC_FORMAT_RAW:
$rsa = new Crypt_RSA();
$pk = array(
'e' => new Math_BigInteger($exp, 16),
'n' => new Math_BigInteger($mod, 16)
);
$rsa->loadKey($pk, CRYPT_RSA_PUBLIC_FORMAT_RAW);
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
echo $rsa->verify($plaintext, $sign) ? 'verified' : 'unverified';
The problem know is to set the correct values in the function verify.
If I just set my signature in hexadecimal I get the notice:
Invalid signature: length = 256, k = 128 in C:\xampp\php\PEAR\Crypt\RSA.php on line 2175
So I have to customize the length of my signature:
$sign_bigInteger = new Math_BigInteger($sign, 16);
$sign_bytes = $sign_bigInteger->toBytes();
echo $rsa->verify($plaintext, $sign_bytes) ? 'verified' : 'unverified';
But the verification is false.
I get the output of the verification function in RSA.php (_rsassa_pkcs1_v1_5_verify) where plaintext is compared with the signature :
//sign
"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0 0*†H†÷ ÖÀZ!Q*y¡ßë*&/"
//plaintext
"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0!0 +•q£îê“O•äQ».åüÓSœÝ["
I don't really understand whats happening in the Class RSA.php.
Can anyone help me and say what I do wrong?
EDIT:
Now I tried to convert my hexString.
$plaintext_bin = pack("H*", $plaintext);
$sign_bin = pack("H*", $sign);
I think that my public key is correct generated, so I just change the input of my verify:
$rsa->verify($plaintext_bin, $sign_bin) ? 'verified' : 'unverified';
Output:
em: string(128) "ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0 0*†H†÷ ÖÀZ!Q*y¡ßë*&/"
em2: string(128) "ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0!0 +ÚÚÿMG‡­ã31G ,;D>7o"
It's still not the same.
EDIT:
I fixed my problem. I forgot to set the Hash:
$rsa1->setHash('md5');
Now it works!
Thank you GregS.
All your values are hex strings. Just convert them using hex2bin() or pack("H*", $hex_string);

Categories