Java CertGetCertificateChain-内存访问无效

Java CertGetCertificateChain-内存访问无效,java,jna,cryptoapi,Java,Jna,Cryptoapi,交叉张贴以提高可见性: 我正在为Crypt32库中的CertGetCertificateChain方法创建一个包装器,我希望获得帮助以解决导致崩溃的“无效内存访问”问题 包装器的签名为: boolean CertGetCertificateChain(Pointer hChainEngine, PCERT_CONTEXT pCertContext, Pointer pTime, Pointer hAdditionalStore, CERT_CHAIN_PARA.ByRef

交叉张贴以提高可见性:

我正在为Crypt32库中的CertGetCertificateChain方法创建一个包装器,我希望获得帮助以解决导致崩溃的“无效内存访问”问题

包装器的签名为:

boolean CertGetCertificateChain(Pointer hChainEngine, PCERT_CONTEXT pCertContext, Pointer pTime,
            Pointer hAdditionalStore, CERT_CHAIN_PARA.ByReference pChainPara, int dwFlags, Pointer pvReserved,
            PointerByReference ppChainContext);
我使用的结构是:

public static class CERT_CHAIN_PARA extends Structure {
    public int cbSize;
    public CERT_USAGE_MATCH RequestedUsage;

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("cbSize", "RequestedUsage");
    }


    public static class ByReference extends CERT_CHAIN_PARA implements Structure.ByReference {}
}


public static class CERT_USAGE_MATCH extends Structure {
    public int dwType;
    public CERT_ENHKEY_USAGE Usage;


    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("dwType", "Usage");
    }


    public static class ByReference extends CERT_USAGE_MATCH implements Structure.ByReference {}
}


public static class CERT_ENHKEY_USAGE extends Structure {
    public int cUsageIdentifier;
    public LPSTR.ByReference rgpszUsageIdentifier;


    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("cUsageIdentifier", "rgpszUsageIdentifier");
    }


    public static class ByReference extends CERT_ENHKEY_USAGE implements Structure.ByReference {}
}
崩溃发生在调用CertGetCertificateChain时。我注意到,将pChainPara设置为null可以阻止它抛出内存访问异常和崩溃。但我不确定这是否是因为pChainPara结构已损坏,或者设置null会迫使它提前失败并在其他地方掩盖问题。我检查了传入的结构的大小,它们与本机代码中的大小匹配

如果我需要提供更多信息,请告诉我。一旦实现和测试,我将清理这个问题,并将证书工作流的包装器和结构提供给JNA

编辑: 我尝试在CERT_CHAIN_PARA中添加其他成员,如下所示:

    public static class CERT_CHAIN_PARA extends Structure {

        public int cbSize;
        public CERT_USAGE_MATCH RequestedUsage;

        public CERT_USAGE_MATCH RequestedIssuancePolicy;
        public int dwUrlRetrievalTimeout;
        public boolean fCheckRevocationFreshnessTime;
        public int dwRevocationFreshnessTime;
        public FILETIME pftCacheResync;
        public CERT_STRONG_SIGN_PARA.ByReference pStrongSignPara;
        public int dwStrongSignFlags;

        @Override
        protected List<String> getFieldOrder() {
            //          return Arrays.asList("cbSize", "RequestedUsage");
            return Arrays.asList("cbSize", "RequestedUsage","RequestedIssuancePolicy","dwUrlRetrievalTimeout","fCheckRevocationFreshnessTime",
                    "dwRevocationFreshnessTime","pftCacheResync","pStrongSignPara","dwStrongSignFlags");
        }

        public static class ByReference extends CERT_CHAIN_PARA implements Structure.ByReference {

        }
    }

    public static class CERT_STRONG_SIGN_SERIALIZED_INFO extends Structure {
        DWORD dwFlags;
        LPWSTR pwszCNGSignHashAlgids;
        LPWSTR pwszCNGPubKeyMinBitLengths;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("dwFlags", "pwszCNGSignHashAlgids", "pwszCNGPubKeyMinBitLengths");
        }

        public static class ByReference extends CERT_STRONG_SIGN_SERIALIZED_INFO implements Structure.ByReference {
        }
    }

    public static class DUMMYUNIONNAME extends Union {
        Pointer pvInfo;
        CERT_STRONG_SIGN_SERIALIZED_INFO.ByReference pSerializedInfo;
        LPSTR pszOID;
    }

    public static class CERT_STRONG_SIGN_PARA extends Structure {
        public int cbSize;
        public int dwInfoChoice;

        public DUMMYUNIONNAME union;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("cbSize", "dwInfoChoice", "union");
        }

        public static class ByReference extends CERT_STRONG_SIGN_PARA implements Structure.ByReference {
        }
    }

    public static class FILETIME extends Structure {

        public int dwLowDateTime;
        public int dwHighDateTime;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("dwLowDateTime", "dwHighDateTime");
        }

        public static class ByReference extends FILETIME implements Structure.ByReference {
        }

        public static class ByValue extends FILETIME implements Structure.ByValue {
        }
    }
}
但是我还是得到了上面提到的失败

编辑2:

PCERT_CONTEXT context = CryptUIDlgSelectCertificateFromStore(store, hwnd,
                "", "", 2, 0, null);

    public static class CERT_CONTEXT extends Structure {

        public int dwCertEncodingType;
        public Pointer pbCertEncoded;
        public int cbCertEncoded;
        public Pointer pCertInfo;
        public Pointer hCertStore;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("dwCertEncodingType", "pbCertEncoded", "cbCertEncoded", "pCertInfo", "hCertStore");
        }

        public static class ByReference extends CERT_CONTEXT implements Structure.ByReference {
        }
    }

    public static class PCERT_CONTEXT extends Structure {

        public CERT_CONTEXT.ByReference certContext;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("certContext");
        }

        public static class ByReference extends PCERT_CONTEXT implements Structure.ByReference {
        }

        public static class ByValue extends PCERT_CONTEXT implements Structure.ByValue {
        }
    }
PCERT\u CONTEXT CONTEXT=CryptUIDlgSelectCertificateFromStore(存储,hwnd,
“”和“”,2,0,空);
公共静态类证书上下文扩展结构{
公共整数编码类型;
公共指针编码;
公共int-cbcert编码;
公共指针pCertInfo;
公共存储;
@凌驾
受保护列表getFieldOrder(){
返回Arrays.asList(“dwCertEncodingType”、“pbCertEncoded”、“cbCertEncoded”、“pCertInfo”、“hCertStore”);
}
公共静态类ByReference扩展证书上下文实现结构。ByReference{
}
}
公共静态类PCERT_上下文扩展结构{
公共证书上下文。通过引用证书上下文;
@凌驾
受保护列表getFieldOrder(){
返回Arrays.asList(“certContext”);
}
公共静态类ByReference扩展了PCERT_上下文实现结构。ByReference{
}
公共静态类ByValue扩展PCERT_上下文实现Structure.ByValue{
}
}

很可能需要定义
证书链_PARA
结构的其余部分,因为其预期大小取决于编译时变量(与
cbSize
中可能提供的内容无关)

注意:仅当CERT\u CHAIN\u PARA\u有额外字段时,才能使用此成员 在包含Wincrypt.h之前,使用#define指令定义。 如果定义了此值,则应用程序必须将所有未使用的字段归零

更新

PCERT\u CONTEXT
CERT\u CONTEXT*
的类型定义。您的Java定义实际上将使其成为
CERT\u CONTEXT**
,至少w/r/t将其作为参数传递。如果您需要本机
CERT\u CONTEXT*
,请使用Java
CERT\u CONTEXT
作为参数类型。在结构中嵌入指针字段可以有效地为被调用方提供希望传递的值的地址,而不是真正希望传递的指针值


通常,您应该省略
.ByReference
符号,除非您定义的结构字段需要为
struct*

类型,默认情况下作为参数传递的结构被视为
struct*
,因此任何
ByReference
标记都是多余的。如果大小匹配,则问题更可能出现在其中一种指针类型中。谢谢。这为我节省了一些时间,无论是否使用“ByReference”都可以尝试。请显示
pCertContext
的定义和构造。完成。我认为上下文是有效的,因为我尝试了一个“CryptoSignMessage”,它起了作用。IIUC,在本机代码中
PCERT\u context
CERT\u context*
的类型定义。您的Java定义实际上将使其成为
CERT\u CONTEXT**
,至少w/r/t将其作为参数传递。如果您需要本机
CERT\u CONTEXT*
,请使用您定义的Java
CERT\u CONTEXT
。我将其与本机实现进行了比较,没有附加变量,如前所述,我得到了相同的大小。我也试过你的建议,但我仍然有这个问题。我将添加新的结构定义和callign代码,作为原始文章的一部分,以获得更好的格式。
pChainPara.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0;
pChainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = null;

pChainPara.dwUrlRetrievalTimeout = 0;
pChainPara.fCheckRevocationFreshnessTime = false;
pChainPara.dwRevocationFreshnessTime = 0;
pChainPara.pftCacheResync.dwHighDateTime = 0;
pChainPara.pftCacheResync.dwLowDateTime = 0;

pChainPara.pStrongSignPara = null;
PCERT_CONTEXT context = CryptUIDlgSelectCertificateFromStore(store, hwnd,
                "", "", 2, 0, null);

    public static class CERT_CONTEXT extends Structure {

        public int dwCertEncodingType;
        public Pointer pbCertEncoded;
        public int cbCertEncoded;
        public Pointer pCertInfo;
        public Pointer hCertStore;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("dwCertEncodingType", "pbCertEncoded", "cbCertEncoded", "pCertInfo", "hCertStore");
        }

        public static class ByReference extends CERT_CONTEXT implements Structure.ByReference {
        }
    }

    public static class PCERT_CONTEXT extends Structure {

        public CERT_CONTEXT.ByReference certContext;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("certContext");
        }

        public static class ByReference extends PCERT_CONTEXT implements Structure.ByReference {
        }

        public static class ByValue extends PCERT_CONTEXT implements Structure.ByValue {
        }
    }