Autor: Saya & Bryce, especialistas em pesquisa de segurança da Beosin
1. O que é prova de conhecimento zero
Prova de Conhecimento Zero (ZKP) é um conceito criptográfico que pode ser usado para provar a autenticidade de uma declaração sem revelar qualquer informação específica sobre a declaração. Numa prova de conhecimento zero, o provador pode provar ao verificador que uma determinada afirmação é verdadeira, e o verificador obtém apenas um resultado: aceitar a afirmação como verdadeira ou rejeitá-la, sem conhecer os detalhes específicos da prova.
Este conceito pode ser explicado com um exemplo simples. Suponha que haja duas pessoas, uma é o provador e a outra é o verificador. O provador quer provar ao verificador que conhece uma senha secreta sem revelar a senha em si. Na forma tradicional, o provador pode dizer ao verificador qual é a senha, mas na prova de conhecimento zero, o provador pode usar um protocolo especial para provar ao verificador que ele sabe a exatidão da senha sem revelar a senha em si.
Atualmente, algoritmos comuns de sistema à prova de conhecimento zero incluem zk-SNARKs, zk-STARKs, BulletProofs, etc.
2. Aplicação de ZKP em blockchain
Na tecnologia blockchain, o ZKP possui uma variedade de aplicações, como melhorar a privacidade, melhorar a escalabilidade e a segurança, etc. Aqui estão algumas aplicações principais do ZKP em blockchain:
1 Proteção de privacidade:
A blockchain é pública, o que significa que qualquer pessoa pode visualizar todas as transações na cadeia. Às vezes, porém, os usuários podem desejar manter a privacidade das informações de suas transações. O ZKP permite aos usuários provar que possuem fundos suficientes para negociar sem ter que divulgar o total de seus fundos. Isso aumenta muito a proteção da privacidade do usuário. Por exemplo, Zcash é uma criptomoeda que usa tecnologia de prova de conhecimento zero, que permite aos usuários ocultar o remetente, o destinatário e o valor de uma transação.
2 Compressão computacional e expansão de blockchain:
A escalabilidade do Blockchain é um desafio, especialmente em aplicações de grande escala. O ZKP pode ser usado para reduzir a carga nos nós e melhorar a escalabilidade de todo o sistema. Ao usar o ZKP para verificar a validade das transações, os nós não precisam visualizar o histórico completo das transações, reduzindo assim a carga de armazenamento e processamento. O ZK Rollup, atualmente o mais utilizado, é uma solução de escalabilidade projetada para melhorar o Ethereum e outras áreas. • Rendimento e eficiência das redes blockchain. Ele combina as vantagens das tecnologias Rollup e ZKP para fornecer soluções de expansão de aplicativos descentralizados (DApps) de alto desempenho. Na rede Ethereum tradicional, cada transação precisa ser verificada e registrada na blockchain, o que resulta em atrasos e custos elevados no processamento das transações. ZK Rollup agrupa e compacta um grande número de transações em um único bloco, e ZKP é usado para provar a validade de transações em lote para garantir a correção e segurança das transações.
3 Autenticação:
As provas de conhecimento zero podem ser usadas para verificar a identidade de um usuário sem revelar informações pessoais confidenciais. Por exemplo, uma pessoa pode usar provas de conhecimento zero para provar à rede que atende a um determinado requisito de idade ou possui uma determinada certificação sem revelar sua idade exata ou outras informações de identificação.
4 Armazenamento Descentralizado:
O servidor pode provar aos usuários que seus dados estão sendo mantidos em segurança e que nenhum conteúdo dos dados é vazado.
Em geral, **a prova de conhecimento zero do blockchain tem amplas aplicações em proteção de privacidade, compressão e expansão de computação, verificação de identidade, armazenamento descentralizado, etc. Ele fornece mais funções e opções para a tecnologia blockchain e promove o desenvolvimento e aplicação de blockchain em diferentes campos. **
3. Ataque de gasto duplo em aplicações ZKP
zk-SNARK (Argumento de conhecimento sucinto e não interativo de conhecimento zero) é uma tecnologia baseada na prova de conhecimento zero que pode provar a autenticidade de uma declaração sem revelar informações reais. É uma tecnologia de prova de conhecimento zero muito eficiente que pode gerar e verificar provas em um tempo muito curto, protegendo a privacidade e a segurança, por isso é amplamente utilizada. Porém, com a expansão das aplicações, sua segurança tem atraído cada vez mais atenção. Descobrimos sua vulnerabilidade geral há pouco tempo: se o intervalo de valores do parâmetro de entrada na função de verificação não for verificado corretamente no projeto ZKP, um invasor pode forjar múltiplas entradas para passar na verificação, causando um ataque de gasto duplo. O impacto deste ataque é muito amplo, envolvendo vários algoritmos zk-SNARK, incluindo: groth16, plonk, etc., e esta vulnerabilidade existe em muitas linguagens de desenvolvimento, como solidity e js. Esta vulnerabilidade foi descoberta pela primeira vez por poma no projeto de prova de conhecimento zero Semaphore, e dois exemplos de transações implementadas com sucesso foram dados, conforme mostrado na figura abaixo:
O princípio de ataque específico desta vulnerabilidade é que se você deseja gerar e verificar a prova zk-SNARK no Ethereum, você precisa usar o circuito de curva elíptica de campo finito F_p-aritmético, onde o valor p é usado para determinar o intervalo do campo finito da curva elíptica, então o circuito A faixa de valores de entrada é [0,1,…,p-1]. Curvas diferentes têm valores de p diferentes:
Curva BN254 definida em EIP-196 (também conhecida como curva ALT_BN128):
p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
circcom2 introduz dois novos primos, as curvas BLS12-381:
p = 52435875175126190479447740508185965837690552500527637822603658699938581184513
e plink2:
18446744069414584321
O Semaphore posteriormente confirmou e corrigiu a vulnerabilidade, e bibliotecas zk como ZoKrates e snarkjs também fizeram reparos de emergência simultaneamente. No entanto, os pesquisadores de segurança da Beosin descobriram que atualmente não há uma solução unificada para este problema. Por exemplo, o protocolo Semaphore grava restrições no emparelhamento biblioteca. O intervalo válido de dados não é verificado explicitamente na lógica de negócios externa; o código do contrato gerado por circcom e Tornado.Cash verifica explicitamente SNARK_SCALAR_FIELD na função de verificação. Esta é uma solução confusa e inconsistente. Pode causar problemas e riscos de segurança para muitas novas partes do projeto zk DApp, por isso esperamos usar uma maneira padronizada para resolver esse problema.
4. Ataque de gasto duplo em ERC-1922
Atualmente, o Ethereum possui um padrão EIP-1922 relacionado ao zk, que introduz a interface padrão do contrato Verify para verificar o zk-SNARK. O código específico é o seguinte:
solidez do pragma ^0.5.6;/// @title EIP-XXXX zk-SNARK Verifier Standard /// @dev Consulte /// Nota: o identificador ERC-165 para esta interface é 0xXXXXXXXX./// ⚠️ TODO: Calcular interface identificadorinterface ERC1922 /* is ERC165 */ { /// @notice Verifica os argumentos da Prova, através de curva elíptica /// funções de emparelhamento. /// @dev /// DEVE retornar verdadeiro se Proof passar em todas as verificações (ou seja, o Proof é /// válido). /// DEVE retornar falso se a Prova não passar em todas as verificações (ou seja, se a /// Prova for inválida). /// @param prova A zk-SNARK. /// @param inputs Entradas públicas que acompanham Proof. /// @param verifyKeyId Um identificador exclusivo (conhecido por este verificador /// contrato) para a chave de verificação à qual Proof corresponde. /// @return result O resultado do cálculo de verificação. True /// se a Prova for válida; falso caso contrário. função verificar (uint256 [] prova de dados de chamada, uint256 [] entradas de dados de chamada, bytes32 verificaçãoKeyId) retornos externos (resultado bool);}
Entre eles, a prova de conhecimento zero e os tipos de variáveis de entrada são uint256[]. Este tipo de variável é atualmente a operação de curva elíptica mais comumente usada no algoritmo ZKP. No entanto, a proteção de segurança correspondente não é adicionada a esta interface, então duplo Também existem ataques a gastos.Um enorme risco à segurança.
5. Solução ERC-7520
Com base nas questões acima, Beosin propôs o EIP-7520 para evitar esse tipo de risco de segurança. Especificamente, todos os projetos DApp que usam a tecnologia zk no ecossistema Ethereum devem implementar essa interface no contrato do verificador compatível para usar padrões unificados e seguros. O método funciona verificação de faixa válida em todas as entradas.A interface específica é a seguinte:
solidez do pragma ^0.5.6;/// @title EIP-XXXX zk-SNARK public inputs Verifier Standard /// Nota: o identificador ERC-165 para esta interface é 0xXXXXXXXX./// ⚠️ TODO: Calcular interface Identifierinterface EIP7520 /* is ERC165 & ERC1922 */ { /// @notice Verifica se os argumentos das entradas estão dentro do campo escalar /// @dev /// DEVE retornar verdadeiro se as entradas passarem na verificação de intervalo (ou seja, as entradas são /// válidas). /// DEVE retornar falso se as entradas não passarem na verificação de intervalo (ou seja, se /// as entradas forem inválidas). /// @param inputs Entradas públicas que acompanham Proof. /// @param p Entrada pública que acompanha a curva. função verifyPublicInput(uint256[] entradas,uint256 p) retornos externos (resultado bool);}
A função verifyPublicInput é o núcleo deste padrão. Os significados específicos dos parâmetros envolvidos são os seguintes:
entradas: definidas como tipo uint256[], representando os parâmetros do sinal público envolvidos na função de verificação no projeto ZKP
p: Definido como tipo uint256, este valor corresponde ao valor p da curva elíptica utilizada no algoritmo
A seguir serão comparadas as duas situações de implementação e não implementação da interface EIP-7520, visando as diferentes manifestações deste ataque, para indicar os riscos para as partes do projeto:
1 Suponha que usemos diretamente o código do contrato de verificação para verificação sem chamar o verifyPublicInput desta interface eip. O código específico é o seguinte:
função verificar (uint [] entrada de memória, prova de memória de prova) visão interna retorna (uint) { VerifyingKey memória vk = verifyingKey(); require(input.length + 1 == vk.IC.length,"verifier-bad-input"); // Calcula a combinação linear vk_x Pairing.G1Point memória vk_x = Pairing.G1Point(0, 0); para (uint i = 0; i < input.length; i++) vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[i + 1], entrada [i] )); vk_x = Emparelhamento.adição(vk_x, vk.IC [0] ); if (!Pairing.pairingProd4( Pairing.negate(prova.A), prova.B, vk.alfa1, vk.beta2, vk_x, vk.gamma2, prova.C, vk.delta2 )) retornar 1; retornar 0;}
Captura de tela dos resultados experimentais originais provando que a verificação foi aprovada:
Ao mesmo tempo, os quatro certificados a seguir podem ser falsificados e também passar na verificação, causando um ataque de gasto duplo:
Usando uma das provas falsificadas, os resultados da verificação são mostrados abaixo:
2 Se a interface verifyPublicInput neste eip for chamada, a prova forjada acima não será verificada. Parte do código do contrato é a seguinte. Para os detalhes restantes, consulte Implementação de referência:
function verifyx(uint[] entradas de memória, prova de memória de prova, bytes32 verifyKeyId,uint256 p) retornos públicos (uint){ require(verifyPublicInput(inputs,p),"verifier-over-snark-scalar-field"); require(verify(inputs,proof,verificationKeyId),"verificação falha"); return true;}função verifyPublicInput(uint256[] inputs,uint256 p) visão interna retorna (bool) { for (uint i = 0; i < input.length; i++) { require(input < p,"verifier-gte-snark -campo escalar"); } retornar verdadeiro;}
Os resultados experimentais são mostrados na figura abaixo:
Em resumo, pode-se constatar que se esta interface não for utilizada para verificar a validade da faixa de valores do sinal público, pode haver risco de ataques de gasto duplo. **
Ver original
Esta página pode conter conteúdo de terceiros, que é fornecido apenas para fins informativos (não para representações/garantias) e não deve ser considerada como um endosso de suas opiniões pela Gate nem como aconselhamento financeiro ou profissional. Consulte a Isenção de responsabilidade para obter detalhes.
Explicação detalhada do rascunho ERC-7520: proteção contra ataque de estouro de entrada pública zk-SNARK
Autor: Saya & Bryce, especialistas em pesquisa de segurança da Beosin
1. O que é prova de conhecimento zero
Prova de Conhecimento Zero (ZKP) é um conceito criptográfico que pode ser usado para provar a autenticidade de uma declaração sem revelar qualquer informação específica sobre a declaração. Numa prova de conhecimento zero, o provador pode provar ao verificador que uma determinada afirmação é verdadeira, e o verificador obtém apenas um resultado: aceitar a afirmação como verdadeira ou rejeitá-la, sem conhecer os detalhes específicos da prova.
Este conceito pode ser explicado com um exemplo simples. Suponha que haja duas pessoas, uma é o provador e a outra é o verificador. O provador quer provar ao verificador que conhece uma senha secreta sem revelar a senha em si. Na forma tradicional, o provador pode dizer ao verificador qual é a senha, mas na prova de conhecimento zero, o provador pode usar um protocolo especial para provar ao verificador que ele sabe a exatidão da senha sem revelar a senha em si.
Atualmente, algoritmos comuns de sistema à prova de conhecimento zero incluem zk-SNARKs, zk-STARKs, BulletProofs, etc.
2. Aplicação de ZKP em blockchain
Na tecnologia blockchain, o ZKP possui uma variedade de aplicações, como melhorar a privacidade, melhorar a escalabilidade e a segurança, etc. Aqui estão algumas aplicações principais do ZKP em blockchain:
1 Proteção de privacidade:
A blockchain é pública, o que significa que qualquer pessoa pode visualizar todas as transações na cadeia. Às vezes, porém, os usuários podem desejar manter a privacidade das informações de suas transações. O ZKP permite aos usuários provar que possuem fundos suficientes para negociar sem ter que divulgar o total de seus fundos. Isso aumenta muito a proteção da privacidade do usuário. Por exemplo, Zcash é uma criptomoeda que usa tecnologia de prova de conhecimento zero, que permite aos usuários ocultar o remetente, o destinatário e o valor de uma transação.
2 Compressão computacional e expansão de blockchain:
A escalabilidade do Blockchain é um desafio, especialmente em aplicações de grande escala. O ZKP pode ser usado para reduzir a carga nos nós e melhorar a escalabilidade de todo o sistema. Ao usar o ZKP para verificar a validade das transações, os nós não precisam visualizar o histórico completo das transações, reduzindo assim a carga de armazenamento e processamento. O ZK Rollup, atualmente o mais utilizado, é uma solução de escalabilidade projetada para melhorar o Ethereum e outras áreas. • Rendimento e eficiência das redes blockchain. Ele combina as vantagens das tecnologias Rollup e ZKP para fornecer soluções de expansão de aplicativos descentralizados (DApps) de alto desempenho. Na rede Ethereum tradicional, cada transação precisa ser verificada e registrada na blockchain, o que resulta em atrasos e custos elevados no processamento das transações. ZK Rollup agrupa e compacta um grande número de transações em um único bloco, e ZKP é usado para provar a validade de transações em lote para garantir a correção e segurança das transações.
3 Autenticação:
As provas de conhecimento zero podem ser usadas para verificar a identidade de um usuário sem revelar informações pessoais confidenciais. Por exemplo, uma pessoa pode usar provas de conhecimento zero para provar à rede que atende a um determinado requisito de idade ou possui uma determinada certificação sem revelar sua idade exata ou outras informações de identificação.
4 Armazenamento Descentralizado:
O servidor pode provar aos usuários que seus dados estão sendo mantidos em segurança e que nenhum conteúdo dos dados é vazado.
Em geral, **a prova de conhecimento zero do blockchain tem amplas aplicações em proteção de privacidade, compressão e expansão de computação, verificação de identidade, armazenamento descentralizado, etc. Ele fornece mais funções e opções para a tecnologia blockchain e promove o desenvolvimento e aplicação de blockchain em diferentes campos. **
3. Ataque de gasto duplo em aplicações ZKP
zk-SNARK (Argumento de conhecimento sucinto e não interativo de conhecimento zero) é uma tecnologia baseada na prova de conhecimento zero que pode provar a autenticidade de uma declaração sem revelar informações reais. É uma tecnologia de prova de conhecimento zero muito eficiente que pode gerar e verificar provas em um tempo muito curto, protegendo a privacidade e a segurança, por isso é amplamente utilizada. Porém, com a expansão das aplicações, sua segurança tem atraído cada vez mais atenção. Descobrimos sua vulnerabilidade geral há pouco tempo: se o intervalo de valores do parâmetro de entrada na função de verificação não for verificado corretamente no projeto ZKP, um invasor pode forjar múltiplas entradas para passar na verificação, causando um ataque de gasto duplo. O impacto deste ataque é muito amplo, envolvendo vários algoritmos zk-SNARK, incluindo: groth16, plonk, etc., e esta vulnerabilidade existe em muitas linguagens de desenvolvimento, como solidity e js. Esta vulnerabilidade foi descoberta pela primeira vez por poma no projeto de prova de conhecimento zero Semaphore, e dois exemplos de transações implementadas com sucesso foram dados, conforme mostrado na figura abaixo:
O princípio de ataque específico desta vulnerabilidade é que se você deseja gerar e verificar a prova zk-SNARK no Ethereum, você precisa usar o circuito de curva elíptica de campo finito F_p-aritmético, onde o valor p é usado para determinar o intervalo do campo finito da curva elíptica, então o circuito A faixa de valores de entrada é [0,1,…,p-1]. Curvas diferentes têm valores de p diferentes:
Curva BN254 definida em EIP-196 (também conhecida como curva ALT_BN128):
p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
circcom2 introduz dois novos primos, as curvas BLS12-381:
p = 52435875175126190479447740508185965837690552500527637822603658699938581184513
e plink2:
18446744069414584321
O Semaphore posteriormente confirmou e corrigiu a vulnerabilidade, e bibliotecas zk como ZoKrates e snarkjs também fizeram reparos de emergência simultaneamente. No entanto, os pesquisadores de segurança da Beosin descobriram que atualmente não há uma solução unificada para este problema. Por exemplo, o protocolo Semaphore grava restrições no emparelhamento biblioteca. O intervalo válido de dados não é verificado explicitamente na lógica de negócios externa; o código do contrato gerado por circcom e Tornado.Cash verifica explicitamente SNARK_SCALAR_FIELD na função de verificação. Esta é uma solução confusa e inconsistente. Pode causar problemas e riscos de segurança para muitas novas partes do projeto zk DApp, por isso esperamos usar uma maneira padronizada para resolver esse problema.
4. Ataque de gasto duplo em ERC-1922
Atualmente, o Ethereum possui um padrão EIP-1922 relacionado ao zk, que introduz a interface padrão do contrato Verify para verificar o zk-SNARK. O código específico é o seguinte:
solidez do pragma ^0.5.6;/// @title EIP-XXXX zk-SNARK Verifier Standard /// @dev Consulte /// Nota: o identificador ERC-165 para esta interface é 0xXXXXXXXX./// ⚠️ TODO: Calcular interface identificadorinterface ERC1922 /* is ERC165 */ { /// @notice Verifica os argumentos da Prova, através de curva elíptica /// funções de emparelhamento. /// @dev /// DEVE retornar verdadeiro se Proof passar em todas as verificações (ou seja, o Proof é /// válido). /// DEVE retornar falso se a Prova não passar em todas as verificações (ou seja, se a /// Prova for inválida). /// @param prova A zk-SNARK. /// @param inputs Entradas públicas que acompanham Proof. /// @param verifyKeyId Um identificador exclusivo (conhecido por este verificador /// contrato) para a chave de verificação à qual Proof corresponde. /// @return result O resultado do cálculo de verificação. True /// se a Prova for válida; falso caso contrário. função verificar (uint256 [] prova de dados de chamada, uint256 [] entradas de dados de chamada, bytes32 verificaçãoKeyId) retornos externos (resultado bool);}
Entre eles, a prova de conhecimento zero e os tipos de variáveis de entrada são uint256[]. Este tipo de variável é atualmente a operação de curva elíptica mais comumente usada no algoritmo ZKP. No entanto, a proteção de segurança correspondente não é adicionada a esta interface, então duplo Também existem ataques a gastos.Um enorme risco à segurança.
5. Solução ERC-7520
Com base nas questões acima, Beosin propôs o EIP-7520 para evitar esse tipo de risco de segurança. Especificamente, todos os projetos DApp que usam a tecnologia zk no ecossistema Ethereum devem implementar essa interface no contrato do verificador compatível para usar padrões unificados e seguros. O método funciona verificação de faixa válida em todas as entradas.A interface específica é a seguinte:
solidez do pragma ^0.5.6;/// @title EIP-XXXX zk-SNARK public inputs Verifier Standard /// Nota: o identificador ERC-165 para esta interface é 0xXXXXXXXX./// ⚠️ TODO: Calcular interface Identifierinterface EIP7520 /* is ERC165 & ERC1922 */ { /// @notice Verifica se os argumentos das entradas estão dentro do campo escalar /// @dev /// DEVE retornar verdadeiro se as entradas passarem na verificação de intervalo (ou seja, as entradas são /// válidas). /// DEVE retornar falso se as entradas não passarem na verificação de intervalo (ou seja, se /// as entradas forem inválidas). /// @param inputs Entradas públicas que acompanham Proof. /// @param p Entrada pública que acompanha a curva. função verifyPublicInput(uint256[] entradas,uint256 p) retornos externos (resultado bool);}
A função verifyPublicInput é o núcleo deste padrão. Os significados específicos dos parâmetros envolvidos são os seguintes:
A seguir serão comparadas as duas situações de implementação e não implementação da interface EIP-7520, visando as diferentes manifestações deste ataque, para indicar os riscos para as partes do projeto:
1 Suponha que usemos diretamente o código do contrato de verificação para verificação sem chamar o verifyPublicInput desta interface eip. O código específico é o seguinte:
função verificar (uint [] entrada de memória, prova de memória de prova) visão interna retorna (uint) { VerifyingKey memória vk = verifyingKey(); require(input.length + 1 == vk.IC.length,"verifier-bad-input"); // Calcula a combinação linear vk_x Pairing.G1Point memória vk_x = Pairing.G1Point(0, 0); para (uint i = 0; i < input.length; i++) vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[i + 1], entrada [i] )); vk_x = Emparelhamento.adição(vk_x, vk.IC [0] ); if (!Pairing.pairingProd4( Pairing.negate(prova.A), prova.B, vk.alfa1, vk.beta2, vk_x, vk.gamma2, prova.C, vk.delta2 )) retornar 1; retornar 0;}
Captura de tela dos resultados experimentais originais provando que a verificação foi aprovada:
Ao mesmo tempo, os quatro certificados a seguir podem ser falsificados e também passar na verificação, causando um ataque de gasto duplo:
Usando uma das provas falsificadas, os resultados da verificação são mostrados abaixo:
2 Se a interface verifyPublicInput neste eip for chamada, a prova forjada acima não será verificada. Parte do código do contrato é a seguinte. Para os detalhes restantes, consulte Implementação de referência:
function verifyx(uint[] entradas de memória, prova de memória de prova, bytes32 verifyKeyId,uint256 p) retornos públicos (uint){ require(verifyPublicInput(inputs,p),"verifier-over-snark-scalar-field"); require(verify(inputs,proof,verificationKeyId),"verificação falha"); return true;}função verifyPublicInput(uint256[] inputs,uint256 p) visão interna retorna (bool) { for (uint i = 0; i < input.length; i++) { require(input < p,"verifier-gte-snark -campo escalar"); } retornar verdadeiro;}
Os resultados experimentais são mostrados na figura abaixo:
Em resumo, pode-se constatar que se esta interface não for utilizada para verificar a validade da faixa de valores do sinal público, pode haver risco de ataques de gasto duplo. **