无法验证签名 ECDSA 密钥
Can't verify signature ECDSA key
我正在尝试使用 javascript 通过 ECDSA 算法创建密钥对,签署消息然后在服务器端验证它(使用 Java)。
示例javascript代码:
// help function
function _arrayBufferToBase64( buffer ) {
var binary = '';
var bytes = new Uint8Array( buffer );
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa( binary );
}
const encodedMessage = new TextEncoder().encode('test');
// keys generation
crypto.subtle.generateKey({
name: 'ECDSA',
namedCurve: 'P-256'
}, true, ['sign','verify']).then((keys) => {
console.log('keys:', keys);
console.log('[....] public key export');
// public key export
crypto.subtle.exportKey('spki', keys.publicKey).then(result => {
console.log('publicKey byte:', result);
console.log('publicKey base64:', _arrayBufferToBase64(result));
// sign
crypto.subtle.sign({
name: 'ECDSA',
hash: {name:'SHA-256'}
},
keys.privateKey,
encodedMessage
).then(signature => {
console.log('signature byte:', signature);
console.log('signature base64:', _arrayBufferToBase64(signature));
// verify
crypto.subtle.verify({
name: 'ECDSA',
hash: {name: 'SHA-256'}
},
keys.publicKey,
signature,
encodedMessage
).then(verified => {
console.log('signature verified?', verified);
});
});
});
});
例如:
publicKey base64: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERhn3GM1eQodijVDdy0Zb+ERjvWZ6idQw8PbaFfTzPdA7oNFh8+AHlni91snTS5Sk2o4Xw9CCnlvHP3uWVyCIvA==
signature base64: nAHPhibM3txezQ53O3C4vMlbQnMI75ILcaamqBezNS51c6wB2ZHwwk/4phgbp+aFlM9omvxaH0fdzJpCT0s/Zg==
signature verified? true
一切都很好。
问题是我无法同时使用 Java 或 this website:
验证同一条消息
Java代码:
private boolean receiver(String message, String algorithm, String signature, String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, UnsupportedEncodingException, SignatureException {
Signature ecdsaVerify = Signature.getInstance(algorithm);
//import org.apache.commons.codec.binary.Base64;
byte[] decodedPk = Base64.decodeBase64(new String(publicKey).getBytes("UTF-8"));
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(decodedPk);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PublicKey pk = keyFactory.generatePublic(publicKeySpec);
ecdsaVerify.initVerify(pk);
byte[] decodedString = new String(message).getBytes("UTF-8");
byte[] decodedSignature = Base64.decodeBase64(new String(signature).getBytes("UTF-8"));
ecdsaVerify.update(decodedString);
boolean result = ecdsaVerify.verify(decodedSignature);
return result;
}
在哪里
String message = "test";
String algorithm = "SHA256withECDSA";
String signature = "nAHPhibM3txezQ53O3C4vMlbQnMI75ILcaamqBezNS51c6wB2ZHwwk/4phgbp+aFlM9omvxaH0fdzJpCT0s/Zg==";
String publicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERhn3GM1eQodijVDdy0Zb+ERjvWZ6idQw8PbaFfTzPdA7oNFh8+AHlni91snTS5Sk2o4Xw9CCnlvHP3uWVyCIvA==";
我得到了这个例外:
[err] java.security.SignatureException: Could not verify signature
[err] at sun.security.ec.ECDSASignature.engineVerify(ECDSASignature.java:325)
[err] at java.security.Signature$Delegate.engineVerify(Signature.java:1223)
[err] at java.security.Signature.verify(Signature.java:656)
[err] at it.bpc.bpwebrs.application.services.IamService.receiver(IamService.java:2740)
[err] at it.bpc.bpwebrs.application.services.IamService.elaboraAbilitazioni(IamService.java:186)
[err] at it.bpc.bpwebrs.infrastructure.servicesImpl.IamResource.eseguiServizioElaborazione(IamResource.java:127)
[err] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[err] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[err] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[err] at java.lang.reflect.Method.invoke(Method.java:498)
[err] at it.bpc.bpwebrs.dispatcher.DispatcherResource.richiamaServizioRichiesto(DispatcherResource.java:447)
[err] at it.bpc.bpwebrs.dispatcher.DispatcherResource.postJSONRequest(DispatcherResource.java:227)
[err] at sun.reflect.GeneratedMethodAccessor77.invoke(Unknown Source)
[err] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[err] at java.lang.reflect.Method.invoke(Method.java:498)
[err] at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.invoke(ResourceMethodInvocationHandlerFactory.java:81)
[err] at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.run(AbstractJavaResourceMethodDispatcher.java:144)
[err] at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161)
[err] at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160)
[err] at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99)
[err] at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389)
[err] at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347)
[err] at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
[err] at org.glassfish.jersey.server.ServerRuntime.run(ServerRuntime.java:326)
[err] at org.glassfish.jersey.internal.Errors.call(Errors.java:271)
[err] at org.glassfish.jersey.internal.Errors.call(Errors.java:267)
[err] at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
[err] at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
[err] at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
[err] at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
[err] at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
[err] at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
[err] at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473)
[err] at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
[err] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388)
[err] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341)
[err] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228)
[err] at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1285)
[err] at [internal classes]
[err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
[err] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
[err] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
[err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
[err] at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
[err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
[err] at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
[err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
[err] at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
[err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
[err] at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
[err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
[err] at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
[err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
[err] at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:155)
[err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
[err] at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
[err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
[err] at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:176)
[err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
[err] at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
[err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
[err] at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
[err] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
[err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
[err] at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
[err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
[err] at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
[err] at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
[err] at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
[err] at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
[err] at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207)
[err] at [internal classes]
[err] at it.bpc.bpwebrs.infrastructure.security.cors.CorsFilter.doFilter(CorsFilter.java:180)
[err] at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207)
[err] at [internal classes]
[err] at it.bpc.bpwebrs.infrastructure.filters.MDCFilter.doFilter(MDCFilter.java:49)
[err] at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207)
[err] at [internal classes]
[err] at it.bpc.bpwebrs.utilities.infrastructure.EncodingFilter.doFilter(EncodingFilter.java:30)
[err] at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207)
[err] at [internal classes]
[err] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[err] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[err] at java.lang.Thread.run(Thread.java:748)
[err] Caused by: java.security.SignatureException: Invalid encoding for signature
[err] at sun.security.ec.ECDSASignature.decodeSignature(ECDSASignature.java:400)
[err] at sun.security.ec.ECDSASignature.engineVerify(ECDSASignature.java:322)
[err] ... 92 more
[err] Caused by: java.io.IOException: Sequence tag error
[err] at sun.security.util.DerInputStream.getSequence(DerInputStream.java:330)
[err] at sun.security.ec.ECDSASignature.decodeSignature(ECDSASignature.java:376)
[err]
... 93 more
我做错了什么?
ECDSA 签名有不同的格式,一方面是 IEEE P1363 (r|s) 格式,另一方面是 ASN.1/DER 编码。
两种格式的关系说明here。
WebCrypto采用IEEE P1363格式,网站和Java代码中的SHA256withECDSA
算法使用ASN.1/DER,这就是问题的原因。
SunEC 提供者还支持 IEEE P1363,为此要应用的算法是 SHA256withECDSAinP1363Format
。有了这个,验证就可以使用 Java 代码。
编辑:
或者,可以使用 BouncyCastle,它支持两种格式:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
...
Security.addProvider(new BouncyCastleProvider());
Signature ecdsaVerify = Signature.getInstance("SHA256withPlain-ECDSA", "BC"); //IEEE P1363
...
我正在尝试使用 javascript 通过 ECDSA 算法创建密钥对,签署消息然后在服务器端验证它(使用 Java)。
示例javascript代码:
// help function
function _arrayBufferToBase64( buffer ) {
var binary = '';
var bytes = new Uint8Array( buffer );
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa( binary );
}
const encodedMessage = new TextEncoder().encode('test');
// keys generation
crypto.subtle.generateKey({
name: 'ECDSA',
namedCurve: 'P-256'
}, true, ['sign','verify']).then((keys) => {
console.log('keys:', keys);
console.log('[....] public key export');
// public key export
crypto.subtle.exportKey('spki', keys.publicKey).then(result => {
console.log('publicKey byte:', result);
console.log('publicKey base64:', _arrayBufferToBase64(result));
// sign
crypto.subtle.sign({
name: 'ECDSA',
hash: {name:'SHA-256'}
},
keys.privateKey,
encodedMessage
).then(signature => {
console.log('signature byte:', signature);
console.log('signature base64:', _arrayBufferToBase64(signature));
// verify
crypto.subtle.verify({
name: 'ECDSA',
hash: {name: 'SHA-256'}
},
keys.publicKey,
signature,
encodedMessage
).then(verified => {
console.log('signature verified?', verified);
});
});
});
});
例如:
publicKey base64: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERhn3GM1eQodijVDdy0Zb+ERjvWZ6idQw8PbaFfTzPdA7oNFh8+AHlni91snTS5Sk2o4Xw9CCnlvHP3uWVyCIvA== signature base64: nAHPhibM3txezQ53O3C4vMlbQnMI75ILcaamqBezNS51c6wB2ZHwwk/4phgbp+aFlM9omvxaH0fdzJpCT0s/Zg== signature verified? true
一切都很好。
问题是我无法同时使用 Java 或 this website:
验证同一条消息Java代码:
private boolean receiver(String message, String algorithm, String signature, String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, UnsupportedEncodingException, SignatureException {
Signature ecdsaVerify = Signature.getInstance(algorithm);
//import org.apache.commons.codec.binary.Base64;
byte[] decodedPk = Base64.decodeBase64(new String(publicKey).getBytes("UTF-8"));
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(decodedPk);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PublicKey pk = keyFactory.generatePublic(publicKeySpec);
ecdsaVerify.initVerify(pk);
byte[] decodedString = new String(message).getBytes("UTF-8");
byte[] decodedSignature = Base64.decodeBase64(new String(signature).getBytes("UTF-8"));
ecdsaVerify.update(decodedString);
boolean result = ecdsaVerify.verify(decodedSignature);
return result;
}
在哪里
String message = "test"; String algorithm = "SHA256withECDSA"; String signature = "nAHPhibM3txezQ53O3C4vMlbQnMI75ILcaamqBezNS51c6wB2ZHwwk/4phgbp+aFlM9omvxaH0fdzJpCT0s/Zg=="; String publicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERhn3GM1eQodijVDdy0Zb+ERjvWZ6idQw8PbaFfTzPdA7oNFh8+AHlni91snTS5Sk2o4Xw9CCnlvHP3uWVyCIvA==";
我得到了这个例外:
[err] java.security.SignatureException: Could not verify signature [err] at sun.security.ec.ECDSASignature.engineVerify(ECDSASignature.java:325) [err] at java.security.Signature$Delegate.engineVerify(Signature.java:1223) [err] at java.security.Signature.verify(Signature.java:656) [err] at it.bpc.bpwebrs.application.services.IamService.receiver(IamService.java:2740) [err] at it.bpc.bpwebrs.application.services.IamService.elaboraAbilitazioni(IamService.java:186) [err] at it.bpc.bpwebrs.infrastructure.servicesImpl.IamResource.eseguiServizioElaborazione(IamResource.java:127) [err] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [err] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) [err] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [err] at java.lang.reflect.Method.invoke(Method.java:498) [err] at it.bpc.bpwebrs.dispatcher.DispatcherResource.richiamaServizioRichiesto(DispatcherResource.java:447) [err] at it.bpc.bpwebrs.dispatcher.DispatcherResource.postJSONRequest(DispatcherResource.java:227) [err] at sun.reflect.GeneratedMethodAccessor77.invoke(Unknown Source) [err] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [err] at java.lang.reflect.Method.invoke(Method.java:498) [err] at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.invoke(ResourceMethodInvocationHandlerFactory.java:81) [err] at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.run(AbstractJavaResourceMethodDispatcher.java:144) [err] at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161) [err] at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160) [err] at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) [err] at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) [err] at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) [err] at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) [err] at org.glassfish.jersey.server.ServerRuntime.run(ServerRuntime.java:326) [err] at org.glassfish.jersey.internal.Errors.call(Errors.java:271) [err] at org.glassfish.jersey.internal.Errors.call(Errors.java:267) [err] at org.glassfish.jersey.internal.Errors.process(Errors.java:315) [err] at org.glassfish.jersey.internal.Errors.process(Errors.java:297) [err] at org.glassfish.jersey.internal.Errors.process(Errors.java:267) [err] at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) [err] at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) [err] at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) [err] at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) [err] at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) [err] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) [err] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) [err] at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) [err] at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1285) [err] at [internal classes] [err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [err] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118) [err] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) [err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [err] at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) [err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [err] at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) [err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [err] at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154) [err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [err] at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) [err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [err] at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150) [err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [err] at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:155) [err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [err] at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199) [err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [err] at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:176) [err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [err] at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110) [err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [err] at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) [err] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [err] at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [err] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [err] at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) [err] at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [err] at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) [err] at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) [err] at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207) [err] at [internal classes] [err] at it.bpc.bpwebrs.infrastructure.security.cors.CorsFilter.doFilter(CorsFilter.java:180) [err] at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207) [err] at [internal classes] [err] at it.bpc.bpwebrs.infrastructure.filters.MDCFilter.doFilter(MDCFilter.java:49) [err] at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207) [err] at [internal classes] [err] at it.bpc.bpwebrs.utilities.infrastructure.EncodingFilter.doFilter(EncodingFilter.java:30) [err] at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207) [err] at [internal classes] [err] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [err] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [err] at java.lang.Thread.run(Thread.java:748) [err] Caused by: java.security.SignatureException: Invalid encoding for signature [err] at sun.security.ec.ECDSASignature.decodeSignature(ECDSASignature.java:400) [err] at sun.security.ec.ECDSASignature.engineVerify(ECDSASignature.java:322) [err] ... 92 more [err] Caused by: java.io.IOException: Sequence tag error [err] at sun.security.util.DerInputStream.getSequence(DerInputStream.java:330) [err] at sun.security.ec.ECDSASignature.decodeSignature(ECDSASignature.java:376) [err] ... 93 more
我做错了什么?
ECDSA 签名有不同的格式,一方面是 IEEE P1363 (r|s) 格式,另一方面是 ASN.1/DER 编码。
两种格式的关系说明here。
WebCrypto采用IEEE P1363格式,网站和Java代码中的SHA256withECDSA
算法使用ASN.1/DER,这就是问题的原因。
SunEC 提供者还支持 IEEE P1363,为此要应用的算法是 SHA256withECDSAinP1363Format
。有了这个,验证就可以使用 Java 代码。
编辑:
或者,可以使用 BouncyCastle,它支持两种格式:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
...
Security.addProvider(new BouncyCastleProvider());
Signature ecdsaVerify = Signature.getInstance("SHA256withPlain-ECDSA", "BC"); //IEEE P1363
...