# `Nfse.Signature`
[🔗](https://github.com/ideia4it/nfse/blob/v0.1.0/lib/nfse/signature.ex#L1)

Uso interno da biblioteca: não faz parte da API pública.

Assinatura XMLDSig envelopada, com C14N inclusiva, da DPS, do pedido de registro de evento e da
NFS-e de decisão judicial.

## Por que não há canonicalização aqui

O XMLDSig digere a forma *canônica* do que assina, não os bytes que vão pela rede. O OTP não traz
C14N, e as dependências da biblioteca também não. Então a biblioteca vai pelo outro caminho: o
escritor do leiaute (`Nfse.Schema.Runtime.encode/4`) já escreve na forma canônica, sem espaço
entre tags, sem `<x/>` e com o namespace só na raiz, e `sign/4` digere os bytes literais. Para
essa forma, a C14N de uma subárvore é a própria subárvore, com uma exceção.

## A exceção: o namespace herdado

A C14N inclusiva escreve no topo do que canonicaliza todo namespace em escopo. O `infDPS` herda
o namespace da NFS-e da `DPS` e não o declara, mas o digest é calculado sobre

    <infDPS xmlns="http://www.sped.fazenda.gov.br/nfse" Id="DPS...">...

Assinar o `<infDPS Id="DPS...">` literal dá uma assinatura bem formada sobre os bytes errados,
e a Sefin responde só "assinatura inválida". Por isso `sign/4` injeta o namespace antes de
digerir. Daí vem a exigência sobre a raiz: ela declara o namespace da NFS-e como padrão e nenhum
outro, porque cada namespace a mais que ela declarasse também entraria no topo da forma canônica.

A mesma regra vale um nível abaixo: o `SignedInfo` herda o namespace do XMLDSig da `Signature`,
então os bytes que o RSA assina levam um `xmlns` que os da rede não levam.

## Onde a assinatura entra

A `Signature` devolvida vai logo depois do elemento assinado, como irmã dele dentro da raiz. Ela
fica fora da subárvore digerida, e a transformação `enveloped-signature` não tira nada dali.

Cada documento leva uma assinatura só. A NFS-e de decisão judicial carrega a DPS sem assinatura
própria (o `Signature` do `TCDPS` é opcional) e só o `infNFSe` é assinado: o digest dele cobre a
DPS embutida.

# `algorithm`

```elixir
@type algorithm() :: :rsa_sha1 | :rsa_sha256
```

# `default_algorithm`

```elixir
@spec default_algorithm() :: algorithm()
```

O algoritmo que a biblioteca usa quando o chamador não escolhe outro.

É `:rsa_sha1` até a conferência na produção restrita.

# `sign`

```elixir
@spec sign(binary(), String.t(), Nfse.Certificate.t(), algorithm()) :: binary()
```

Assina `element` e devolve a `<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">` que vai
logo depois dele, como irmã dentro da raiz.

`element` são os bytes literais e canônicos do elemento, exatamente como vão aparecer no
documento final, e `id` é o valor do atributo `Id` dele, para onde a `Reference` aponta. A raiz
que recebe o elemento declara o namespace da NFS-e como padrão e nenhum outro.

Levanta `ArgumentError` quando `element` não está na forma que este módulo sabe digerir. É de
propósito: cada um desses casos daria uma assinatura de aparência válida sobre os bytes errados,
e o único retorno seria a recusa da Sefin, dias depois.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
